Perlで複素数列挙をshort coding
ネタ元は、@javascripter さんのPOST(http://twitter.com/javascripter/statuses/8367943818)
for(a=[],b=[],c=1;c++<1E3;)if(!a[c])for(b.push(d=c);d<1E3;a[d+=c]=1);alert("素数" + b);
と、id:nitoyon さんのActionScript3 で素数列挙を short coding (3) - てっく煮ブログ 跡地。
で、Perlだとどのくらい短く書けるのかやってみた。
ルールみたいなものとしては nitoyonさんに習って、
「結果の表示方法は問わない」ってことと、「warningとか気にしない*1」ってことくらい。
やってみた、結果はこんな感じに。
for($c=1;$c++<1E3;){if(!$a[$c]){for(push @b,($d=$c);$d<1E3;$a[$d+=$c]=1){}}}die"@b" # 83文字
Perlならではの書き方とかできればよかったのだが、
私の知識では、普通にjavascripterさんのコードの移植に。。。orz
nitoyonさんが紹介していたトリッキーなコード(正確には、psyarkさんとo8queさんのコード)
でもやってみたが、
for($c=$d=2;$a{$c}||$d>2E3?($d=++$c)<1E3:($b{$c}=1);){$a{$d+=$c}=1}@b=keys%b;die"@b" # 84文字
結果表示部分が短くできず*2。
もっと面白い書き方があれば、教えて欲しいです。
【追記1 (2010-02-16 21:13)】
コメントありがとうございます!
余裕のprint出力参りましたorz
map{$a=$_;$c=2;map{$c++if$a%$_}2..$a;push@b,$a if$c==$_}1..1E3;print join"\n",@b # 80文字
die出力すると70文字までいくので、JSよりも短いです!
map{$a=$_;$c=2;map{$c++if$a%$_}2..$a;push@b,$a if$c==$_}1..1E3;die"@b" # 70文字
もっと短くするには、mapかgrepかなぁとは思いつつも、諦めた口なので、とても勉強になりました!
【追記2 (2010-02-18 21:15)】
grepで頑張ってみたらかなり短くなった!
@b=(2..1E3);for$c(@a=@b){@b=grep$c==$_||$_%$c,@b}die"@b" # 56文字
【追記3 (2010-03-07 22:41)】
知らなかったんですが、正規表現を使う有名な(?)short codeがあるっぽいですね。
それを元にしたものが以下。
map{warn$_ if(1x$_)!~/^(11+)\1+$/}2..1E3 # 40文字
grepでも頑張ってみましたが、表示する部分で文字数を減らせませんでした。
die"@{[grep{(1x$_)!~/^(11+)\1+$/}2..1E3]}" # 42文字
これ以上はあるんでしょうか。
【追記ここまで】
-
-
- -
-
ちなみに、javascripterさんのJSは、
for(a=[],b=[],c=1;c++<1E3;)if(!a[c])for(b.push(d=c);d<1E3;a[d+=c]=1);alert(b) // 77文字
nitoyonさんが紹介していたテクニックで書き直すと、
for(a=[],b={},c=d=2;a[c]||d>2E3?(d=++c)<1E3:b[c]=1;)a[d+=c]=1;console.log(b) // 76文字
1文字短くできるけど、console.log出力はちょっと反則かもしれない。