Question

i want to use the functional way to count this and i want to count them efficiently so i do not want to store the sequence, just go through it and count the numbers

let conjv2 x =
    let next n = match n%2 with
                 |0 -> n/2
                 |_ -> n*3+1
    Seq.initInfinite next
    |> Seq.takeWhile(fun n -> n > 1)
    |> Seq.length

this does not work and returns 0 for any positive number, it is the 3n+1 conjecture and i am finding it really hard to count them efficiently, this code works fine but i want to do it the functional way :

let conj x =
    let mutable ansa = x
    let mutable cycles = 1
    while ansa > 1 do
        cycles <- cycles+1
        ansa <- match ansa%2 with
                |0 -> ansa/2
                |_ -> ansa*3+1
    cycles
Was it helpful?

Solution

The key problem with the sample is that you're using Seq.initInfinite instead of Seq.unfold.

  • Seq.initInfinite calls the specified function with the index of the element as argument (0, 1, 2, ..)
  • Seq.unfold calls the specified function with the state generated by the previous iteration

Note that your code also does not use the argument x and so your function ends up being 'a -> int rather than int -> int which is what you'd expect - this is a good indication that there is something wrong!

To fix this, try something like this:

let conjv2 x =
    let next n = match n%2 with
                 |0 -> n/2
                 |_ -> n*3+1
    Seq.unfold (fun st -> let n = next st in Some(n, n)) x
    |> Seq.takeWhile(fun n -> n > 1)
    |> Seq.map (fun v -> printfn "%A" v; v)
    |> Seq.length

The function passed to unfold needs to return an option with the new state & a value to emit. To generate infinite sequence, we always return Some and the emitted values are the intermediate states.

This returns values that are smaller by 2 than your original conj, because conj starts with 1 (rather than 0) and it also counts the last value (while here, we stop before ansa=1). So you'll need to add 2 to the result.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top