読者です 読者をやめる 読者になる 読者になる

Ruby1.8でtwitter idのQuineを書いた

Quine(クワイン)とは,自身のソースコードを出力するプログラムのことです.
クワイン (プログラミング) - Wikipedia

今回は見よう見真似でRubyで作ってみました.
参考:Google Code Jam

TwitterではLinda_ppというアカウントで投稿しているので,それを大文字で使ってみました.
大文字にしたのは面積を稼ぐためです.

eval($q=              "$q='eva    l($q=%    p.split    *%p)'%[$q,''               ];$o=                                    0;(m=%q_efg!q      !+b<b/tj{f/uj
 nft|}j                }u>b\\      j^<qsj    ou)j&      3>>1@(!(+u;%             r\\%p-u                                    ^*<%p,>u!jg)j      &3>>2*~<qvut<
  foe_                  ).si        ze.tim   es{|        i|m[    i]-=           1};eval(m                                    );p(     0,8,      14,8     ,4,6
  ,4,7                  ,4,1        2,15,5,  36,1        3,6,     13);         p(1,   6,16                                   ,6,6     ,6,4      ,5,6     ,12,
  13,7                  ,36,        13,6 ,13 );p(        2,4,     18,4        ,8,6     ,3,4                                  ,8,4,4,4,11,       9,36,4,5,4,6
  ,4,5                  ,4);        p(2,  4,18,4,        8,7,     2,4,       8,4,5,4,9,4,3,4                                 ,35,4,5,4,6        ,4,5,4);p(2
  ,4,1                  8,4,        8,4,   1,3,1,        4,8,    4,5,       4,8,4,5,4,34,12,7                                ,12)               ;p(2
 ,4,18,4,8,4,2,7       ,8,4,5      ,4,7,    15,33,      11,8,11);p(2       ,4,18         ,4,8,      4,3,6,8,4,4,4,7,17,      32,4              ,15,4
);p(1,15,7,6,6,5,     4,6,6,12    ,7,5,9,    5,6,19    ,6,4,14,5);p      (0,17,5,8     ,4,7,4,6,   4,12,6,9,5,9,3,21,3,8   ,11,9)".           split*"")

等幅フォントを使っていないと多分ずれてしまうので,等幅フォントを設定しているエディタにコピペするか,Gistで見ることをおすすめします.
AA-Quine — Gist

このソースコードをAA_quine.rbなどの名前で保存し,Ruby1.8で実行すると,そのソースコード自身が出力されます.

% ruby AA_quine.rb | diff - AA_quine.rb

とすると何も出力されないので,元のソースコードと完全に一致した出力であることが分かります.

書いてみて分かったのは,ソースコードを短く書くいわゆるコードゴルフの能力がかなり必要です.
Rubyはevalが使えるのでかなりQuineが楽な言語ですが,それでもソースコードの文字数を減らすのにかなり苦労しました.
こうしてみると上のGoogleのQuineはソースコードのサイズを小さくする色々な工夫がされていることが分かります.僕はコードゴルフの知識は無いので,最初にメソッドを定義して,そのメソッドをひたすら呼び出すという単純な構造で書きました.
ただしスペースと"が使えないので,少しだけ工夫してあります.その過程で文字列をバイト列として処理するRuby1.8が好都合でした.