2016-05-10 39 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 但正如其他更有效的解决方案中的评论所隐含的。