Search code examples
swiftswift3sequencefibonacci

Fibonacci numbers generator in Swift 3


The following Q&A covers a few methods of generating Fibonacci numbers in Swift, but it's quite outdated (Swift 1.2?):

Question: How could we generate Fibonacci numbers neatly using modern Swift (Swift >= 3)? Preferably methods avoiding explicit recursion.


Solution

  • An alternative for Swift 3.0 would be to use the helper function

    public func sequence<T>(first: T, while condition: @escaping (T)-> Bool, next: @escaping (T) -> T) -> UnfoldSequence<T, T> {
        let nextState = { (state: inout T) -> T? in
            // Return `nil` if condition is no longer satisfied:
            guard condition(state) else { return nil }
            // Update current value _after_ returning from this call:
            defer { state = next(state) }
            // Return current value:
            return state
        }
        return sequence(state: first, next: nextState)
    }
    

    from Express for loops in swift with dynamic range:

    for f in sequence(first: (0, 1), while: { $1 <= 50 }, next: { ($1, $0 + $1)}) {
        print(f.1)
    }
    // 1 1 2 3 5 8 13 21 34
    

    Note that in order to include zero in the resulting sequence, it suffices to replace the initial value (0, 1) by (1, 0):

    for f in sequence(first: (1, 0), while: { $1 <= 50 }, next: { ($1, $0 + $1)}) {
        print(f.1)
    }
    // 0 1 1 2 3 5 8 13 21 34
    

    That makes the "artificial" check

    if pair.1 == 0 { pair.1 = 1; return 0 }
    

    redundant. The underlying reason is that the Fibonacci numbers can be generalized to negative indices (https://en.wikipedia.org/wiki/Generalizations_of_Fibonacci_numbers):

     ... -8, 5, -3, 2, -1, 1, 0, 1, 1, 2, 3, 5, 8, ...