Quineの書き方メモ

Perl最短

一番簡単なquineはコレ?

open 0;print<0>

ただ、これは標準入力からだとダメなのでpipeで繋げる使い方はできない。

$ cat quine.pl
open 0;print<0>
$ perl quine.pl
open 0;print<0>
$ perl quine.pl | perl
$

print+eval

pipeでも使えるようにするには、こういう書き方がある

$_=q{print"\$_=q{$_};eval"};eval

これなら何度でもpipeで繋げられる。

$ cat quine2.pl
$_=q{print"\$_=q{$_};eval"};eval
$ cat quine2.pl | perl
$_=q{print"\$_=q{$_};eval"};eval
$ cat quine2.pl | perl | perl
$_=q{print"\$_=q{$_};eval"};eval

引数を明示的に与える方式だとこう?

$ cat quine3.pl
eval($_=q{print"eval(\$_=q{$_})"})
$ cat quine3.pl | perl
eval($_=q{print"eval(\$_=q{$_})"})
$ cat quine3.pl | perl | perl
eval($_=q{print"eval(\$_=q{$_})"})

おそらくこれが、eval使える言語では結構一般的に使われているquineのテクニック。
Quine ruBy Perl版 - すぎゃーんメモも、これに色々手を加えた形で作っている。

記号化

evalと言えば記号プログラミング。上記のを

$_=';eval{print"\$_=".chr(39).$_.chr(39).$_}';eval{print"\$_=".chr(39).$_.chr(39).$_}

と変形。evalする部分を拡張正規表現記法にし、("$_"はうまく動かないので適当な特殊変数におきかえ)

$^=';""=~/(?{print"\$^=".chr(39).$^.chr(39).$^})/';""=~/(?{print"\$^=".chr(39).$^.chr(39).$^})/

文字列化

$^=';""=~("(?{".q{print"\$^=".chr(39).$^.chr(39).$^}."})")';""=~("(?{".q{print"\$^=".chr(39).$^.chr(39).$^}."})")

排他的論理和に置換

$^=';""=~("(?{".("__).+_}_#}_"^"/-@\@_}!{}@}").".".("}[_"^"_|}").".".("_}"^"{#").".".("}|_"^"_[}").".".("_#"^"{}")."})")';""=~("(?{".("__).+_}_#}_"^"/-@\@_}!{}@}").".".("}[_"^"_|}").".".("_}"^"{#").".".("}|_"^"_[}").".".("_#"^"{}")."})")

で、できあがり。

$ cat quine4.pl
$^=';""=~("(?{".("__).+_}_#}_"^"/-@\@_}!{}@}").".".("}[_"^"_|}").".".("_}"^"{#").".".("}|_"^"_[}").".".("_#"^"{}")."})")';""=~("(?{".("__).+_}_#}_"^"/-@\@_}!{}@}").".".("}[_"^"_|}").".".("_}"^"{#").".".("}|_"^"_[}").".".("_#"^"{}")."})")
$ cat quine4.pl | perl
$^=';""=~("(?{".("__).+_}_#}_"^"/-@\@_}!{}@}").".".("}[_"^"_|}").".".("_}"^"{#").".".("}|_"^"_[}").".".("_#"^"{}")."})")';""=~("(?{".("__).+_}_#}_"^"/-@\@_}!{}@}").".".("}[_"^"_|}").".".("_}"^"{#").".".("}|_"^"_[}").".".("_#"^"{}")."})")
$ cat quine4.pl | perl | perl
$^=';""=~("(?{".("__).+_}_#}_"^"/-@\@_}!{}@}").".".("}[_"^"_|}").".".("_}"^"{#").".".("}|_"^"_[}").".".("_#"^"{}")."})")';""=~("(?{".("__).+_}_#}_"^"/-@\@_}!{}@}").".".("}[_"^"_|}").".".("_}"^"{#").".".("}|_"^"_[}").".".("_#"^"{}")."})")