Skip to content

Instantly share code, notes, and snippets.

@dfrib
Last active October 23, 2016 20:03
Show Gist options
  • Save dfrib/b74a15cc6f97d7576c0fad4ca7046836 to your computer and use it in GitHub Desktop.
Save dfrib/b74a15cc6f97d7576c0fad4ca7046836 to your computer and use it in GitHub Desktop.
Fibonacci numbers generation for Swift 3.0 & 3.1, using sequence(state:, next:) function
// --------------------------------------------------------------- //
// Swift 3.0:
func fibs(through: Int, includingZero useZero: Bool = false)
-> UnfoldSequence<Int, (Int, Int)> {
return sequence(state: useZero ? (1, 0) : (0, 1),
next: { (pair: inout (Int, Int)) -> Int? in
return pair.1 <= through ? {
defer { pair = (pair.1, pair.0 + pair.1) }
return pair.1 }() : nil
})
}
// explicit type annotation of inout parameter closure
// needed due to (current) limitation in Swift's type
// inference
// alternatively, always start from one: drop useZero conditional
func fibs1(through: Int)
-> UnfoldSequence<Int, (Int, Int)> {
return sequence(state: (0, 1),
next: { (pair: inout (Int, Int)) -> Int? in
return pair.1 <= through ? {
defer { pair = (pair.1, pair.0 + pair.1) }
return pair.1 }() : nil
})
}
// -----------------
// example usage
// fib numbers up through 50, excluding 0
fibs(through: 50).forEach { print($0) }
// 1 1 2 3 5 8 13 21 34
// ... inluding 0
fibs(through: 50, includingZero: true).forEach { print($0) }
// 0 1 1 2 3 5 8 13 21 34
// project Euler #2: sum of even fib numbers up to 4000000
print(fibs(through: 4_000_000)
.reduce(0) { $1 % 2 == 0 ? $0 + $1 : $0 }) // 4 613 732
// --------------------------------------------------------------- //
// Swift 3.1:
// making use of Sequence method 'prefix(while:)', in so dropping
// the need for explicit sequence termination by 'nil'
func fibs(through: Int, startingFromZero useZero: Bool = false)
-> AnySequence<Int> {
return sequence(state: useZero ? (1, 0) : (0, 1),
next: { (pair: inout (Int, Int)) -> Int? in
defer { pair = (pair.1, pair.0 + pair.1) }
return pair.1
}).prefix(while: { $0 <= through })
}
// alternatively, always start from 1: drop useZero conditional
func fibs1(through: Int) -> AnySequence<Int> {
return sequence(state: (0, 1),
next: { (pair: inout (Int, Int)) -> Int? in
defer { pair = (pair.1, pair.0 + pair.1) }
return pair.1
}).prefix(while: { $0 <= through })
}
// examples: see above
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment