Skip to content

Instantly share code, notes, and snippets.

@proxpero
Created October 13, 2015 18:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save proxpero/445b8de0a2006da195a7 to your computer and use it in GitHub Desktop.
Save proxpero/445b8de0a2006da195a7 to your computer and use it in GitHub Desktop.
Project Euler problem 43 in Swift
//: [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