5

12 番目のプロジェクトのオイラー問題を解きながら、連続する三角数を得るために無限数列を作成しました。私の最初の試みは:

let slowTriangularNumbers =

  let rec triangularNumbersFrom n = 
    seq { 
      yield seq { 0 .. n } |> Seq.sum
      yield! triangularNumbersFrom (n + 1) 
    }

   triangularNumbersFrom 1

これは非常に遅いことが判明しました。次の項目を取得するたびに、 までのすべての加算を計算する必要がありましたn

私の次の試みは:

let fasterTriangularNumbers =

  let cache = System.Collections.Generic.Dictionary<int, int>()
  cache.[0] <- 0         

  let rec triangularNumbersFrom n = 
  seq { 
    cache.[n] <- cache.[n - 1] + n                   
    yield cache.[n]
    yield! triangularNumbersFrom (n + 1) 
  }

  triangularNumbersFrom 1

可変ディクショナリを導入したことでかなり高速化されましたが、これは可変コレクションを持つのが普通なのでしょうか、それとも状態を表す別の方法はありますか?

4

1 に答える 1

8

これはより慣用的だと思います:

Seq.unfold (fun (i, n) -> Some(n, (i+1, n+i))) (2, 1)

この代替手段を好むかもしれません:

seq { 2 .. System.Int32.MaxValue }
|> Seq.scan (+) 1
于 2013-12-27T19:19:19.280 に答える