当达到条件时,以无限序列获得数字计数

时间:2014-05-05 22:27:37

标签: f#

我想使用功能方式对此进行计数,我想有效地计算它们,所以我不想存储序列,只需通过它并计算数字

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

这不起作用并返回任何正数的0,这是3n + 1猜想,我发现很难有效地计算它们,这段代码工作正常,但我想以功能的方式做到:

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

1 个答案:

答案 0 :(得分:3)

示例的关键问题是您使用的是Seq.initInfinite而不是Seq.unfold

  • Seq.initInfinite调用指定的函数,并将元素的索引作为参数(0,1,2,..)
  • Seq.unfold使用上一次迭代生成的状态调用指定的函数

请注意,您的代码也不使用参数x,因此您的函数最终为'a -> int而不是int -> int,这是您所期望的 - 这是一个很好的指示有什么不对劲的!

要解决此问题,请尝试以下方法:

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

传递给unfold的函数需要返回一个新状态&amp;要发出的值。为了生成无限序列,我们总是返回Some,并且发出的值是中间状态。

这会返回比原始conj小2的值,因为conj以1(而不是0)开头,并且它还计算最后一个值(在此处,我们在{{{}之前停止1}})。因此,您需要在结果中添加2。