Created
October 13, 2015 18:08
-
-
Save proxpero/445b8de0a2006da195a7 to your computer and use it in GitHub Desktop.
Project Euler problem 43 in Swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: [Sub-string Divisibility](https://projecteuler.net/problem=43) | |
/*: | |
The number, 1406357289, is a 0 to 9 pandigital number because it is made up of each of the digits 0 to 9 in some order, but it also has a rather interesting sub-string divisibility property. | |
Let d[1] be the 1st digit, d[2] be the 2nd digit, and so on. In this way, we note the following: | |
* d[2]d[3]d[4] = 406 is divisible by 2 | |
* d[3]d[4]d[5] = 063 is divisible by 3 | |
* d[4]d[5]d[6] = 635 is divisible by 5 | |
* d[5]d[6]d[7] = 357 is divisible by 7 | |
* d[6]d[7]d[8] = 572 is divisible by 11 | |
* d[7]d[8]d[9] = 728 is divisible by 13 | |
* d[8]d[9]d[10] = 289 is divisible by 17 | |
Find the sum of all 0 to 9 pandigital numbers with this property. | |
*/ | |
// Xcode 7.0, Swift 2.0 | |
import Cocoa // for NSDate to calculate performance | |
func permute(current: [Int]) -> [Int] { | |
var i = current.count | |
// search backwards through the array for the head index of longest, non-increasing suffix | |
// set it to `i` | |
repeat { | |
i-- | |
// if we get to the startIndex then there is no higher lexicographic permutation | |
guard i > 0 else { return [] } | |
} while (current[i - 1] >= current[i]) | |
// the 'pivot' will be the value at index i - 1 | |
// search through the suffix for the rightmost successor the the pivot | |
var j = current.count - 1 | |
while (current[j] <= current[i - 1]) { | |
j--; | |
} | |
// create a mutable copy of `current` to hold the next mutation | |
var next = current | |
// swap the pivot with its rightmost successor | |
let temp = next[i - 1] | |
next[i - 1] = next[j] | |
next[j] = temp | |
// reverse the suffix (in effect sorting the suffix in non-decreasing order) | |
j = next.count - 1 | |
while (i < j) { | |
let temp = next[i] | |
next[i] = next[j] | |
next[j] = temp | |
i++ | |
j-- | |
} | |
return next | |
} | |
let divisors = [2, 3, 5, 7, 11, 13, 17] | |
func test(digits: [Int]) -> Bool { | |
var success = true | |
for index in (0..<divisors.count) { | |
let n = 100 * digits[index + 1] + 10 * digits[index + 2] + 1 * digits[index + 3] | |
if n % divisors[index] != 0 { | |
success = false | |
break | |
} | |
} | |
return success | |
} | |
func calculate() -> Int { | |
var result = 0 | |
var next = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | |
repeat { | |
// if the number has the divisibility property... | |
if test(next) { | |
// add it to the result. | |
result += next.reduce(0) { 10 * $0 + $1 } | |
} | |
next = permute(next) | |
} while next != [] | |
return result | |
} | |
func evaluateBlock(block: () -> Int) { | |
let start = NSDate() | |
let result = block() | |
let end = NSDate() | |
let timeInterval: Double = end.timeIntervalSinceDate(start) | |
print("solution of \(result) reached in \(timeInterval) seconds") | |
} | |
evaluateBlock(calculate) | |
// An Xcode playground is too slow to run this code. Create a new Commannd Line Tool project. | |
// I know this code could be optimized, but I can understand what's happening better this way. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment