お遊び記事です.【追記】お遊びのつもりが,とても秀逸な別解がコメント欄に集まりましたので,そちらもぜひ御参照下さい.とりあえず,J言語すげえ.
アルゴリズムと実装
主に関数型リスト処理を用いて,$x$を$2〜x-1$の各整数で割った余りのリストに0が含まれていなければ$x$を素数と判定しています.このため,任意範囲の整数リスト生成(range
等),リスト各要素への関数適用(map
等),リストに特定の値が含まれているかの判定(include
等),条件を満たした要素のみをリストから取り出す処理(filter
等)を行う関数があると,より短いワンライナーとなります.
各言語での記述例
$1<n<100$の$n$について素数判定を行った結果を表示しています.どうしても長くなりがちなので,字句解析が可能な程度に空白等を詰めています.
Ruby
>> ->n{(2...n).reject{|x|(2...x).map{|z|x%z}.include?(0)}}[100]
=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Haskell
> (\n->filter(\x->not$elem 0$(\x->map(\z->rem x z)[2..x-1])x)[2..n])100
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
Python
>>> (lambda n:[x for x in range(2,n)if not 0 in map(lambda z:x%z,range(2,x))])(100)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Clojure
user=> ((fn[n](filter(fn[x](not((set(map #(mod x %)(range 2 x)))0)))(range 2 n)))100)
(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97)
JavaScript
> (n=>(r=>r(n).filter(x=>!(i=>r(i).map(z=>i%z).includes(0))(x)))(n=>[...Array(n-2)].map((v,k)=>k+2)))(100)
[ 2,
3,
//(途中結果は省略)
97 ]
Scheme
> ((lambda(n)(filter(lambda(x)(not(member 0(map(lambda(z)(modulo x z))(cddr(iota x))))))(cddr(iota n))))100)
(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97)
備考
記事に関する補足
- ~~JavaScriptに範囲生成関数が標準で用意されていないのがちょっと意外.~~最近のJavaScriptでは
[...Array(n).keys()].slice(s)
あたりが定番の模様(コメントより).
更新履歴
- 2020-12-10:Clojureの例を追加
- 2020-12-04:冒頭にコメント欄参照の旨追記
- 2020-12-04:初版公開(Ruby,Haskell,Python,JavaScript,Scheme)