Euler problem 2 in Scala
The 2nd project Euler problem is also rather trivial:
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, …
Find the sum of all the even-valued terms in the sequence which do not exceed four million.
Creating a fibonacci method in Scala is trivial:
1 | def fib(n: Int):Int = if (n <= 2) 1 else fib(n-2)+fib(n-1) |
Since this is a recursive function, we need to explicitly declare the return type, as Scala can’t infer it from the method body alone. The method is however badly recursive. Scala does support tail recursion, that is recursion when the last statement off the method calls itself. However here the method calls itself before the end, so tail recursion can’t be used. This causes an exponential row off calls. Rewriting the method so it employs tail recursion, it looks like this:
1 2 | def fib(n:Int, a:Int, b:Int):Int = if (n==0) a else fib(n-1, b, a+b) def fib(n:Int):Int = fib(n, 1, 0) |
The 2nd method here is just a shorthand for the first. We recursivly call ourselves with decreasing n until n reaches 0, in which case argument a will hold the correct answer. Since this is a tail recursive call, Scala is able to rewrite it into a loop instead, thus avoiding deep stack frames and StackOverflow exceptions.
However, calculating increasing fibonacci numbers until we reach the max of 4 million is not effective. We keep throwing away the calculations from each step even though we could use it for the next number. What we need instead is a method for iterating over all the fibonacci numbers. In python this would be a generator functions, but atm. I don’t know the equivalent in Scala. Instead I went for a method creating a list of Fibonacci numbers:
1 2 3 4 5 | def fib(max: Int, a: Int, b: Int):List[Int] = { if (a+b < max) a+b :: fib(max, b, a+b) else List() } def fib(max: Int):List[Int] = fib(max, 0, 1) |
The 2nd method is the one we will normally call, which calls to the first to do the actual work. Here we use the List concatenation operation in scala, ::. This will prepend the expression on the left (a+b) to the list on the right (fib(max, b, a+b)). This is because the default Lists in Scala are immutable LinkedLists, so adding to the start is a cheap operation.
With the method for generating fibonacci numbers in hand, it’s easy to calculate the sum off all even fibonacci numbers below 4 million. We just need to filter out the even numbers, then appply a reduce function:
1 | println(fib(4000000) filter(_%2==0) reduceRight(_+_)) |
The full program then becomes:
1 2 3 4 5 6 7 8 9 | object Euler002 extends Application { def fib(max: Int, a: Int, b: Int):List[Int] = { if (a+b < max) a+b :: fib(max, b, a+b) else List() } def fib(max: Int):List[Int] = fib(max, 0, 1) println(fib(4000000) filter(_%2==0) reduceRight(_+_)) } |
A note of caution here. All my methods use Int, which will overflow quickly for fibonacci numbers. If larger numbers are needed, use Long or BigInt. BigInt has all the common math operations overloaded, so it’s just as easy to use as Int in the above code.
