itmuckel
itmuckel

Reputation: 1420

F# - Return element from sequence

Spoiler-Alert! You'll see a solution for projecteuler.net-Problem 7.

I am sorry if this is a duplicate, but I could not find a question here asking the same.

I compute a sequence of numbers in a function and want to return the nth number.

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 will always be 2, but why?

When I evaluate the last expression in PrimeNumber with nth=10001 then the correct item is returned. Am I missing something?

Upvotes: 0

Views: 507

Answers (2)

s952163
s952163

Reputation: 6324

You want Seq.filter if you need to stick to this solution:

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 will give you 541 But as eluded to in the comments that are other more efficient solutions.

Upvotes: 2

Pash101
Pash101

Reputation: 641

The issue lies in your use of Seq.find.

Seq.find, from the documentation, returns the first element for which the condition is true. In this case, that is 2.

Therefore, your unfolder expression will simply generate an infinite sequence of 2s, so whatever element you take, it will always be a 2.

To see this, run just this snippet of your code:

2
|> Seq.unfold unfolder

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

Upvotes: 2

Related Questions