2016-05-10 4 views
0

Spoiler-Alert! Вы увидите решение для 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, но почему?

Когда я вычисляю последнее выражение в PrimeNumber с nth=10001, тогда верный элемент возвращается. Я что-то упускаю?

ответ

2

Проблема заключается в использовании Seq.find.

Seq.find, из документации, возвращает первый элемент, для которого выполняется условие. В этом случае, то есть 2.

Таким образом, ваше выражение Unfolder будет просто генерировать бесконечную последовательность 2s, поэтому любой элемент, который вы берете, это всегда будет 2.

Чтобы увидеть это, запустить именно этот фрагмент кода:

2 
|> Seq.unfold unfolder 

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

Изменение '|> fun e -> Some (e, e)' to '|> fun e -> Some (e, e + 1)' исправлено. Спасибо за подсказку. После перезапуска визуальной студии он не оценил правильное решение. Я не знаю, почему это сработало раньше. – itmuckel

+0

@ Micha90: пересмотреть 'e + 1' - это будет проверять каждое четное число бессмысленно. – ildjarn

+0

Что вы предлагаете? e + 2 пропускает 3 как штрих, когда я начинаю с 2. Также он дает неправильное решение, nth + 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 Но так же, как в комментариях, это другие более эффективные решения.

Смежные вопросы