Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create sequence based on previous value

Tags:

sequence

f#

I'm learning F# (second day O:-)) and I want to create Collatz sequence, where is every value computed based on previous one. I know, ho to do it in C#

public static void Main(string[] args)
{
    Console.WriteLine(string.Join(", ", collatz(13)));
}

static IEnumerable<int> collatz(int n)
{
    while (n != 1)
    {
        yield return n;

        if (n % 2 == 0)
            n /= 2;
        else
            n = 3 * n + 1;
    }

    yield return 1;
}

or how to create array like that in F#

let rec collatz = function
    | 1 -> [ 1 ]
    | n when n % 2 = 0 -> n::collatz (n / 2)
    | n -> n::collatz (3 * n + 1)

collatz 13 |> Seq.map string |> String.concat ", " |> printfn "%s"

but don't figure out sequence solution...

like image 302
Matěj Pokorný Avatar asked Dec 01 '22 16:12

Matěj Pokorný


2 Answers

You can do it pretty concisely using Seq.unfold...

let collatzSeq = Seq.unfold <| function 
    | 1 -> Some(1, -1) 
    | -1 -> None 
    | n when n % 2 = 0 -> Some(n, n / 2) 
    | n -> Some(n, 3 * n + 1)
like image 191
Joel Mueller Avatar answered Dec 04 '22 15:12

Joel Mueller


You can use a sequence expression:

let rec collatzSeq n = seq {
    match n with
    | 1 -> yield 1
    | n when n % 2 = 0 ->
        yield n
        yield! collatzSeq (n / 2)
    | n ->
        yield n
        yield! collatzSeq (3 * n + 1)
}
like image 26
Lee Avatar answered Dec 04 '22 15:12

Lee