最近正在看F#, 拿Project Eular來練手。
順便用Haskell做一遍,對比一下。
No1.
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
F# : [1..999] |> List.filter ( fun x -> (x % 3 = 0) || (x % 5 = 0) ) |> List.sum;;
Haskell: answer = sum . filter (\ x -> (x `mod` 3 == 0) || (x `mod` 5 == 0) ) $ [ 1..999 ]
Answer: 233168
後語: (.) 函數用起來比 |> 感覺好。
No2.
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.
F# :
let answer =
let d = new System.Collections.Generic.Dictionary<int,int>()
let rec fibCache n = if d.ContainsKey(n) then d.[n]
else if n <= 2 then 1
else let res = fibCache (n-2) + fibCache (n-1)
d.Add(n,res)
res
let rec num n = if fibCache n < 4000000 then num (n + 1) else n
let pos = num 1
let nd = d.Remove(pos)
d |> Seq.map ( fun (KeyValue(k, v)) -> if v % 2 = 0 then v else 0 ) |> Seq.sum
Haskell : --note: 效率低。 F#,将中間結果cache到一個dictionary中,速度快些。
fibPair n = foldl (\ (x,y) n -> (y, x+y) ) (1, 1) [3..n]
answer = sum . filter even . takeWhile ( < 4000000) . scanl ( \ acc n -> snd $ fibPair n ) 0 $ [1.. ]
Answer: 4613732
後語:F# 對象與函數式的混合,亂,不過對從imperative轉來的有親切感。