我对Project Euler上的problem 2解决方案的最后一步感到困惑。这是我到目前为止得到的消息来源。
#light
module pe2 (* Project Euler Problem 2 solution *)
open System
let Phi = 1.6180339887;;
let invPhi = 1.0/Phi;;
let rootOfFive = 2.236067977;;
let maxFib = 4000000.0;
let Fib n =
System.Math.Round((Phi**n - invPhi**n)/rootOfFive);;
let FibIndices = Seq.unfold(fun i -> Some(i, i+3.0)) 3.0;;
let FibNos = FibIndices |> Seq.map(fun index -> Fib(index));;
let setAllowedFibNos = FibNos |> Seq.filter(fun fn -> (fn <= maxFib));;
// let answer = setAllowedFibNos |> Seq.fold (+) 0.0;
当我取消注释最后一行时,该过程似乎永远不会完成。所以我希望有人可以在正确的方向上给我一个轻柔的推动。我确实看了setAllowedFibNos并且它看起来正确但它也是一个无限序列所以我只看到前三个术语。
另外,有人能指出我将各种序列链接在一起的正确方法吗?我试过这样的事情:
let answer = Seq.unfold(fun i-> Some(i, i + 3.0)) 3.0
|> Seq.map (fun index -> Fib(index))
|> Seq.filter(fun fn -> (fn <= maxFib))
|> Seq.fold (+) 0.0;;
但那没用。你可能猜到我只是在学习F#所以请温柔一点,如果之前已经问过并回答了这类问题,请发一个答案的链接,我会撤回这个。
答案 0 :(得分:4)
let rec Fib(n) =
if (n < 2) then
1
else
Fib(n-2) + Fib(n-1)
Seq.initInfinite Fib
|> Seq.takeWhile (fun a -> a <= 4000000)
|> Seq.filter (fun a -> (a % 2) = 0)
|> Seq.fold (+) 0
答案 1 :(得分:3)
'setAllowedFibNos'确实是一个无限的seq计算; 'fold'需要整个序列,因此'filter'将永远运行,寻找另一个数字&lt; = maxFib。
看看takeWhile:
我认为这是你想要的而不是过滤器。
另请注意,您可以使用'sqrt 5.0'。
答案 2 :(得分:0)
我仍然在尝试习惯Seq方法。但是,没有它,这是我的解决方案。
#light
let rec fib n =
match n with
|0|1 -> n
|_ -> fib(n-1) + fib(n-2)
let maxFib = 4000000
let phi = (1.0 + sqrt(5.0)) / 2.0
let upperBound = 1 + int( log10((float(maxFib) - 0.5) * sqrt(5.0)) / log10(phi))
[1..upperBound] |> List.filter (fun x-> x%3=0) |> List.map fib |> List.filter (fun x -> x%2 = 0) |> List.filter (fun x -> x List.sum |> printfn "%d"
答案 3 :(得分:0)
我的解决方案是:
Seq.unfold (fun state ->
if (fst state + snd state > 4000000) then None
else Some(fst state + snd state, (snd state, fst state + snd state))) (0,1)
|> Seq.filter (fun x -> x % 2 = 0)
|> Seq.sum;;