Swift: Project Euler Challenge – Fibonacci

Today’s challenge is Euler problem #2. I wanted to start with a less intense problem yesterday because I felt that despite its low Project Euler number, that Problem 2 has a lot more interesting things going for it. Here’s the basic problem:

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …

By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

When I first solved this problem as I was just learning Swift, I did so in a fairly obvious way, which is as you see here:

var fib = [Int]()
fib += 1
fib += 2
var sum = 2
while fib[fib.count - 1] < 4000000 {
    fib += fib[fib.count - 2] + fib[fib.count - 1]
    let lastItem = fib[fib.count - 1]
    if lastItem < 4000000 {
        if lastItem % 2 == 0 {
            sum += lastItem
        }
    }
}
sum

But coming back to it later, I was inspired to completely re-think the problem, to try to, how do I put this?, make it Swiftier, put more Swift in it, Swifticize it.

Here’s what I ended up with:

The later version (I hesitate to say final, even now) uses a generator instead of an array.  Only the most recent two terms are stored at any time, ensuring both fixed storage and fixed computation time. It may be a bridge too far in terms of overcomplicating a simple problem but I was pretty pleased with this result.

struct FibGenerator : Generator {
    typealias Element = Int
    var i = 0, j = 0
    mutating func next() -> Int? {
        if (i == 0) {i = 1; return 1}
        if (j == 0) {j = 2; return 2}
        var sum = i + j; i = j; j = sum
        return sum
    }
}

var fib = FibGenerator()
var sum = 0
var current : Int = 0
while current < 4000000 {
    if current % 2 == 0 {sum += current}
    current = fib.next()!
}
sum

As always, please let me know your tweaks, suggestions, and alternatives by Email, Twitter, or comments. Cheers!

3 Comments