project euler problem 10
昨日取得した素数列を生み出す関数ですぐ終わると思ったが計算時間が半端じゃなかった
main=print $ sum $takeWhile (<2000000) primes primes = sieve [2..] sieve (p:xs) = p:[x|x<-sieve xs,mod x p/=0]
だめだ。このアルゴリズムだとスタックオーバーフローだ。
$ time ./a.out Stack space overflow: current size 8388608 bytes. Use `+RTS -Ksize' to increase it. real:483m33.969s,user:483m18.400s,sys:0m17.361s $ free total used free shared buffers cached Mem: 2061216 1866800 194416 0 422980 1222672 -/+ buffers/cache: 221148 1840068 Swap: 9765616 0 9765616
もうすこしスワップのあるマシンにしよう。
あと、2以上の奇数でのみ行うことにしてと…
$ cat 10-2.hs main=print $ sum $ takeWhile (<2000000) primes primes = sieve (2:[3,5..]) sieve (p:xs) = p:[x|x<-sieve xs,mod x p/=0] $ time ./10-2 Stack space overflow: current size 8388608 bytes. Use `+RTS -Ksize' to increase it. real:583m8.805s,user:582m47.733s,sys:0m23.197s
くぅこれでもだめだ
エラトステネスの篩は x1 / 2 以下の素数が既知のとき、(x1 / 2 以上)x 以下の素数を決定するには、x 以下の整数で x1 / 2 以下の素数の倍数を全て取り除けば(=篩えば)よいことを意味する。このことから、包除原理を用いることによって x 以下の素数の個数に関する式を得ることができる。
なんと…√2以下で行うのがエラトステネスの篩じゃん…
内包表記で√2以下に限定する方法がわからない…どんなガードを書けばいいんだろう…
main=print $ sum $ takeWhile (<2000000) primes primes = 2:filter isPrime [3,5..] isPrime n = all (\x->mod n x/=0) $ takeWhile (\x->x^2<=n) primes
無限に呼び合う二つの再帰関数か。むずかしい。
$ time ./a.out 142913828922 real:0m19.820s,user:0m19.789s,sys:0m0.032s
よし。できた。
でも内包表記ではまだわからない。