Perlメモ ナベアツ ワンライナー その3

3の倍数と3のつく数字のときにアホになって、さらに5の倍数のときに犬っぽくなるワンライナー


前回書いたのがこれで、139文字。

perl -e '@nabe=qw/0 aho! bow! ahooown!!/; 
map {$n=0; $n+=1 if(!($_%3)||/3/); $n+=2 if(!($_%5)); print $nabe[$n]?$nabe[$n]:$_,"\n"} (1..40)'

よく考えると、無駄なところがあったので、もうちょっと短くしてみる。
目指せ100文字!!


最初に気がついたのが、
print文中の $nabe[$n]?$nabe[$n]:$_ の部分。
$n が 0 のときは @nabe の1番目「0」で”偽”とする、という回りくどいやりかた。
よく考えれば、 $n が 0 の時はそれ自体が”偽”なので、配列の中身の評価は必要ない。

perl -e '@nabe=qw/0 aho! bow! ahooown!!/; 
map {$n=0; $n+=1 if(!($_%3)||/3/); $n+=2 if(!($_%5)); print $n?$nabe[$n]:$_,"\n"} (1..40)'

132文字。


そうなると、配列を使う場所が一カ所になるので、@nabeも必要なくなる
ついでに print を map の外に出した。見た目の問題で。というか何故中に入れた?

perl -e 'print map {$n=0; $n+=1 if(!($_%3)||/3/); $n+=2 if(!($_%5)); 
$n?qw/0 aho! bow! ahooown!!/[$n]:$_,"\n"} (1..40)'

119文字。一気に減った。いい感じ。


配列の1番目を変数を展開させれば、三項演算子自体不要では?

perl -e 'print map {$n=0; $n+=1 if(!($_%3)||/3/); $n+=2 if(!($_%5)); 
qw/$_ aho! bow! ahooown!!/[$n],"\n"} (1..40)'

失敗。qw//の中では変数は展開されないみたい。


気を取り直して、無駄な部分をそぎ落とす。
改行文字は"$n"でなく、$/ に変更。-2文字で117文字。
if と .. の () は省略できる。-6文字で111文字。
{} の前後や ; の後ろの空白もカット。-5文字で106文字。

perl -e 'print map{$n=0;$n+=1 if!($_%3)||/3/;$n+=2 if!($_%5); 
$n?qw/0 aho! bow! ahooown!!/[$n]:$_,$/}1..40'

106文字。


配列の1番目が”偽”であるという最初の考えから、
三項演算子の部分は || で変更可能だった。-2文字で104文字。

perl -e 'print map{$n=0;$n+=1 if!($_%3)||/3/; $n+=2 if!($_%5); 
qw/0 aho! bow! ahooown!!/[$n]||$_,$/}1..40'


$n=0 の直後の $n+=1 は $n++ に置き換えられる。-1文字で103文字。
3の倍数と3のつく数字の判定は、ビット演算子でもOK? -1文字で102文字。
あと、$n=0 ってのも無くして、$/ を $n に代入すれば、数値としては 0 として扱われる。-2文字で100文字!

perl -e 'print map{$n++ if!($_%3)|/3/;$n+=2 if!($_%5);qw/0 aho! bow! ahooown!!/[$n]||$_,$n=$/}1..40'

100文字!


このあと、ifの前の空白も削除できる事がわかったので、さらに-2文字で98文字になりました。

perl -e 'print map{$n++if!($_%3)|/3/;$n+=2if!($_%5);qw/0 aho! bow! ahooown!!/[$n]||$_,$n=$/}1..40'

98文字。僕にはこれが限界です。