K A N O U . J P さんところを見ていて(続きを読まずに)、791 が素数かどうかちょっと気になったので。
791 isPrime "=> Unknown selector, please confirm, correct, or cancel "
とか、ありそうでない。w わからんでもないけど。
n |
コスト無視とは言え、あれば最後に来ることが分かっていて「含むかどうか」を訊くのはちょっと気持ち悪い。
(Integer primesUpTo: n) last = n
でも、last のレシーバは #() かもしれない。
#() last "=> Error: this collection is empty "
かといって、
({1}, (Integer primesUpTo: n)) last = n
([(Integer primesUpTo: n) last] ifError: [1]) = n
などと、逃げを打つのもいかがなものか。
はっ!(…わざとらしく) #() なのは n = 1 のときだけじゃないか…。<バカ?
(n > 1 ifTrue: [(Integer primesUpTo: n) last]) = n
でいいじゃん。もっとも、はなからメソッドにしたりする気はないので、前の方の、
(Integer primesUpTo: n) last = n
で、いいんですけどね…。orz
もちろん、Integer class >> #primesUpTo: などというマニアックなメソッドを探す手間かける前に、
((1 to: n) select: [: each | n \\ each = 0]) size = 2
とか、これじゃさすがにアレなんで、
((2 to: n // 2) select: [: each | n \\ each = 0]) isEmpty
って素直に書いちゃったほうが(因数が欲しいとかで つぶしが利くし)早いんですが。
ただ #select: の実装では、レシーバと同サイズ配列の領域をまず確保してしまうので、あまり大きな数には使えません。そういった意味でも #primesUpTo: は大きめの数に対処するなどちょっとインテリジェントなところがあるので、前のほうのでも言うほど悪くないのかも。
ところで、エラトステネスの篩いって Smalltalk とか Ruby のコレクションとイテレータ(Ruby の場合はブロック付きメソッド)を使ってエレガントに書くとどうなるんでしょうかねぇ…。
もとい、そもそもエレガントに書けるものなんでしょうか(^_^;)。結局、コストが高くつきそうで…。こうなると、Cマガに載っていると言われるアルゴリズムも気になります。
篩の目を interval で表現して蓄積、チェックしたりしてみましたが、いまひとつ。
limit primeIntervals |