以下の ruby コード A を実行すると別の ruby コード B を出力します。で、その出力されたコード B を実行するとまた元のコード A を出力します。かつ、コード A とコード B は同じキャラクタを含んでいません。
eval q=%q(puts ('DIGGB%sB'%(('eval q=%q('+q+')').bytes.map{|c|'L%o'%c}*'')).tr'A-Z','!-%;-?[-]')
以下説明とか。
実行すると一旦違うコードになって戻ってくる Quine というのはよく考えるわけです。考えるんですよ! ですけど、これは普通の quine
printf q="printf q=%p,q",q
に変数を一個追加したら終わりで、
a=0;printf q="a=%d;printf q=%p,1-a,q",1-a,q
なんてやってやれば OK です。 a=1 と a=0 を巡回してぐるぐる回るはず。
これの何が面白くないかというと、2つのプログラムの見た目がほとんど同じことじゃないかと思います。というわけで、見た目が全然違う2つのプログラムが循環するといいかなぁと思いました。「見た目が全然違う」というのは定義が難しいですが、なるべく厳しい条件で考えると、2つのプログラムで使われている文字で同じものが無い、とでもすればいいかなぁと思ったのが上記のコードです。
上記のコードはコード B の方が非常に単純な構造なんで、コード A の方は割と好き勝手コードが書ける感じで、まぁそこまで難しい感じではなかったのでした。
その前に書いたコードは以下のもので、こっちの方が長い上に生成されるコードがバイナリを含んでいて ruby1.9 で実行できないくせに、苦労しています。
c=[ m='JD48PCIkPjw8XCIiKyJjPVsgIG09JyN7bX0nXQpsPWxhbWJkYSAmOnVucGFj awpjWzFdPSAnbScKbD1sWypjXQpldmFsICAgKmwiLnRyKCIALX8iLCKALf8i KSsgIlwiLnRyKFwigC3/XCIsXCIALX9cIiki '] l=lambda &:unpack c[1]= 'm' l=l[*c] eval *l
ピリオドとかカンマを取り除くために、
l=m.unpack('m')
を
l=lambda &:unpack c=[m] c[1]='m' l=l[*c]
とかしてるのが少し面白いかもしれません。このへん使うと3つのコードを巡回して、その3つのコードが同じ文字を含んでない、とかも頑張ればできるかもしれません…
さて、このルールだと、書けない言語が結構多いと思います。 C なんか main を必ず書かないといけないので、書けないと思います。 Java なんかはユニコード文字のエスケープがあるから書けるんじゃないかなと。
なるべく違う見た目…ということで最初に考えたのは編集距離を最大化するって制限で、これだと多少ゆるい縛りになるんで、 C なんかでも書けそうな気がします。 Brainfuck とかですらできないとは断言できない気がします。本当かな…
そういうことを考えていて、編集距離を最大化するにはこうすればいい、みたいなシステマチックな方法があるのかなぁ…とか考えはじめたのですが、どうもよくわからんでした。同じ文字(列)を使う時は何バイト以上離さないといけない、とかそういうのが色々あると思うのですが…