Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sum of Fibonacci term using Functional Swift

I'm trying to learn functional Swift and started doing some exercises from Project Euler.

Even Fibonacci numbers Problem 2 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.

Implemented a memoized Fibonacci function, as per WWDC advanced Swift videos:

func memoize<T:Hashable, U>( body: ((T)->U,T) -> U) -> (T)->U {
  var memo = [T:U]()
  var result: ((T)->U)!
  result = { x in
    if let q = memo[x] { return q }
    let r = body(result,x)
    memo[x] = r
    return r
  }
  return result
}

let fibonacci = memoize { (fibonacci:Int->Double,n:Int) in n < 2 ? Double(n) : fibonacci(n-1) + fibonacci(n-2) }

and implemented a class that conforms to the Sequence protocol

class FibonacciSequence: SequenceType {
  func generate() -> GeneratorOf<Double> {
      var n = 0
      return GeneratorOf<Double> { fibonacci(n++) }
  }

  subscript(n: Int) -> Double {
      return fibonacci(n)
  }
}

The first (non-functional) solution of the problem:

var fib = FibonacciSequence().generate()
var n:Double = 0
var sum:Double = 0
while n < Double(4_000_000) {
  if n % 2 == 0 {
    sum += n
  }
n = fib.next()!
}

println(sum)

The second, more functional solution, using ExSwift for it's takeWhile function

let f = FibonacciSequence()
println((1...40).map { f[$0] }
                .filter { $0 % 2 == 0 }
                .takeWhile { $0 < 4_000_000 }
                .reduce(0, combine: +))

I'd like to improve on this solution, because of the 1...40 range at the begging that's calculating too many terms for no reason. Ideally I'd like to be able to have some sort of infinite range, but at the same time only calculate the required terms that satisfy the condition in the takeWhile

Any suggestions ?

like image 588
Lescai Ionel Avatar asked May 25 '15 15:05

Lescai Ionel


People also ask

What is a Fibonacci sequence in Swift?

Swift Fibonacci Numbers Implement the Fibonacci method. Use an iterative version in a for-loop. Fibonacci. This is an important numeric sequence. In the Fibonacci sequence, each number is the sum of the two previous numbers. This sequence is found in many parts of our world.

How to find the i-th Fibonacci number?

Given a number positive number n, find value of f 0 + f 1 + f 2 + …. + f n where f i indicates i’th Fibonacci number. Remember that f 0 = 0, f 1 = 1, f 2 = 1, f 3 = 2, f 4 = 3, f 5 = 5, … Attention reader! Don’t stop learning now.

What is the relation between the sum of Fibonacci numbers and numbers?

# by Nikita tiwari. The idea is to find relationship between the sum of Fibonacci numbers and n’th Fibonacci number. F (i) refers to the i’th Fibonacci number. We can rewrite the relation F (n+1) = F (n) + F (n-1) as below F (n-1) = F (n+1) - F (n) Similarly, F (n-2) = F (n) - F (n-1) . . . . . . . . .

How do you find the sum of Fibonacci numbers in Python?

In order to find S (n), simply calculate the (n+2)’th Fibonacci number and subtract 1 from the result. F (n) can be evaluated in O (log n) time using either method 5 or method 6 in this article (Refer to methods 5 and 6). # Python 3 Program to find sum of # Fibonacci numbers in O (Log n) time.


1 Answers

Here I generate the sequence that already stops once max value is reached. Then you just need to reduce without filtering, just sum 0 when n is odd.

func fibonacciTo(max: Int) -> SequenceOf<Int> {
    return SequenceOf { _ -> GeneratorOf<Int> in
        var (a, b) = (1, 0)
        return GeneratorOf {
            (b, a) = (a, b + a)
            if b > max { return nil }
            return b
        }
    }
}


let sum = reduce(fibonacciTo(4_000_000), 0) {a, n in (n % 2 == 0) ? a + n : a }

As an alternative, if you wish to keep fibonacci a more general function you could extend SequenceOf with takeWhile and reduce1 obtaining something that resembles function composition:

 extension SequenceOf {
    func takeWhile(p: (T) -> Bool) -> SequenceOf<T> {
        return SequenceOf { _ -> GeneratorOf<T> in
            var generator = self.generate()
            return GeneratorOf {
                if let next = generator.next() {
                    return p(next) ? next : nil
                }
                return nil
            }
        }
    }

    // Reduce1 since name collision is not resolved
    func reduce1<U>(initial: U, combine: (U, T) -> U) -> U {
        return reduce(self, initial, combine)
    }
}


func fibonacci() -> SequenceOf<Int> {
    return SequenceOf { _ -> GeneratorOf<Int> in
        var (a, b) = (1, 0)
        return GeneratorOf {
            (b, a) = (a, b + a)
            return b
        }
    }
}

let sum2 = fibonacci()
    .takeWhile({ $0 < 4_000_000 })
    .reduce1(0) { a, n in (n % 2 == 0) ? a + n : a}

Hope this helps

like image 153
Matteo Piombo Avatar answered Oct 10 '22 14:10

Matteo Piombo