2016-05-10 38 views
0

擾流板警報!你會看到projecteuler.net-問題7的解決方案。F# - 從序列中返回元素

如果這是重複的,我很抱歉,但是在這裏我找不到問題。

我計算一個函數中的數字序列,並希望返回第n個數字。

let isPrime x = 
    {2..x/2} 
    |> Seq.exists (fun e -> x%e=0) 
    |> not 

let PrimeNumber nth = 
    let unfolder a = 
     a 
     |> Seq.unfold (fun e -> Some(e, e+1)) 
     |> Seq.find isPrime 
     |> fun e -> Some(e, e) 

    2 
    |> Seq.unfold unfolder 
    |> Seq.skip (nth-1) 
    |> Seq.head 

let ans = PrimeNumber 10001 

ans將永遠是2,但爲什麼?

當我用nth=10001評估PrimeNumber中的最後一個表達式時,返回正確的項目。我錯過了什麼嗎?

回答

2

問題在於您使用Seq.find。

Seq.find,從文檔,返回第一元件的量,條件爲真。在這種情況下,也就是2

因此,您的展平表達只會產生2秒的無限序列,所以無論元素你拿,它將永遠是一個2

看到這一點,只運行該你的代碼片段:

2 
|> Seq.unfold unfolder 

//output: val it : seq<int> = seq [2; 2; 2; 2; ...] 
+0

更改'|> fun e - >某些(e,e)'到'|> fun e - >某些(e,e + 1)'固定它。感謝提示。重新啓動visual studio後,它沒有評估正確的解決方案。我不知道爲什麼它以前工作。 – itmuckel

+0

@ Micha90:重新考慮'e + 1' - 它會毫無意義地測試每一個偶數。 – ildjarn

+0

你有什麼建議?當我從2開始時,e + 2跳過3作爲素數。它也會產生錯誤的解,即第n + 1個素數。它跑得不快,但我看不出爲什麼。我預計它的運行速度會快兩倍。 – itmuckel

3

你想Seq.filter如果你需要堅持這種解決方案:

let isPrime x = 
{2..x/2} 
|> Seq.exists (fun e -> x%e=0) 
|> not 

let PrimeNumber nth = 
    let unfolder a = 
     a 
     |> Seq.unfold (fun e -> Some(e, e+1)) 
     |> Seq.filter isPrime 

    2 
    |> unfolder 
    |> Seq.skip (nth-1) 
    |> Seq.item 0 

let ans = PrimeNumber 100會給你541 但正如其他更有效的解決方案中的評論所隱含的。