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出力はちょっと反則かもしれない。

*1:なので、use strict したら怒られます

*2:結果のソートもされてません