I was practicing a bit with Haskell to get to know the language (It's amazing) so I went to project euler and did problem #2 which took quite a while (~ 30-40s I don't know how long exactly) to finish. I wondered why it took so long so I tried the same with F#, C# Javascript and Python. F# and C# took a couple of ms to finish as well as javascript but python took more time than Haskell did. Why is that? These are my implementations
Haskell
fib 0 = 1
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
genFibs n maxVal =
if fib n < maxVal then
fib(n):(genFibs (n+1) maxVal)
else []
totalSum = sum (filter even (genFibs 1 4000000))
main = print totalSum
F#
let rec fib n =
match n with
| n when n < 2 -> 1
| n -> fib (n-1) + fib (n-2)
let rec genFibos n max =
match fib(n) < max with
| true -> fib(n)::(genFibos (n + 1) max)
| false -> []
genFibos 1 4000000
|> Seq.where (fun n -> n % 2 = 0)
|> Seq.sum
C#
static int Fib(int n)
{
return n < 2 ? 1 : Fib(n - 1) + Fib(n - 2);
}
public static int EvenFibs()
{
var n = 1;
var totalSum = 0;
var num = 1;
while(num < 4000000)
{
num = Fib(n);
if (num % 2 == 0) totalSum += num;
n += 1;
}
return totalSum;
}
Python
knownVals = { }
def fib(n):
if n not in knownVals:
knownVals[n] = 1 if n < 2 else fib(n-1) + fib(n-2)
return knownVals[n]
n = 1
stillCounting = True
totalSum = 0
while stillCounting:
num = fib(n)
if num > 4000000:
stillCounting = False
else:
if num % 2 == 0:
totalSum += num
n += 1
print(totalSum)
Javascript
(function () {
function fib(n) {
return n < 2 ? 1 : fib(n - 1) + fib(n - 2);
}
var totalSum = 0;
var num = 1;
var n = 1;
while(num < 4000000)
{
num = fib(n);
if (num % 2 == 0) totalSum += num;
n += 1;
}
alert(totalSum);
})();
So can someone explain why Haskell and Python were slow and the F# and C# were fast on this and how I can enhance it? Any help would be appreciated!
EDIT: Haskell code corrected, Python better implementation using memoization