コードは、「セクシー素数ベンチ(の非効率な実装)」を移植したもの。
open System.Linq let isPrime n = Enumerable.Range(2, n - 2) // {2..n-1} |> Seq.forall (fun i -> n % i <> 0) let sexyPrimes n = Enumerable.Range(9, n - 8) // {9..n} |> Seq.map (fun i -> [|i-6; i|]) |> Seq.filter (fun i -> Array.forall isPrime i) [<EntryPoint>] let main args = let sw = new System.Diagnostics.Stopwatch() sw.Start() let c = sexyPrimes 100000 |> Seq.length sw.Stop() printfn "%A" sw.Elapsed printfn "%A" c 0
Enumerable.Range
を使うと6秒強で終わる処理なのに、{..}
を使うと46秒程度かかってしまう。
rst76が
自分の中で、F#の内包表記は使わないというルールができつつあります。
と書いてたけど、シーケンスの範囲演算子も使わないほうがいいのかな…… どうも、F#が作ってくれるシーケンスが重そうだ(シーケンスが返すEnumeratorが重そう)。
(追記)などとぼやいていたら、殺伐としたTLにMSMVP for VBAF#が登場!
そうか F# のシーケンス(が返すEnumerator)がぽっちゃり実装なんだな。
2013-04-02 16:38:34 via web
自己解決にめげずにコメント付けに行くべきかどうか。
@igeta R!F!C! R!F!C!
2013-04-02 17:45:42 via web to @igeta
@igeta 120秒を超えました!
2013-04-02 19:09:30 via web to @igeta
@matarillo そして let range n m = Seq.unfold (fun n -> if n <= m then Some (n, n+1) else None) n にするとちょっとマシになるっていう。
@igeta 18秒を切りました! 結構変わるものですね。なんか遅いなーと思ったらプロファイル取ったりfscのソースを眺めたりして、自分のコードを書き換えないといけませんね (fscを改造して賢くできるような技能は持ってないので)
2013-04-02 19:38:06 via web to @igeta
@matarillo シーケンス式イコール悪ってわけでもないんですよーと言いたかったのです! むしろ根深い。。
大変参考になりました。ありがとうございましたいげ太さん!