山手Quineのid:ku-ma-meさんに敬意を表しつつ.
うどんげQuine
ソースコードがうどんげのAAになっているQuineコードを作ってみた.Gistはこちら.
udonge_quine.rb
eval$s =%w' b= " BAhsKwG vfg A AAAAA PAAA AIw AA AAA gD8AAAA4 AQA AA Ph 4AAAAcAMAA ICDf wA A AOAGAADA8D8 AAAD wB g AAQPwfAAAA eAY AA E D/AwAAA DgGA AB A fwAAAAA 8DAAA QH 8 AAA AAf BgAABB 3A AAA A PhhAAC OfgAAA A D wgwCA4G 8A AAAA g If4f/4fAAAAA AD+PuC+AgAAA ACA+wXA 7gAAA AAA wD4AA O A DAA AAAOAB A gA AHg AAA AB wGAEB CP0AA AAAe I wNs4 nvD wA A A H T EtaWO7 woAA AB q4 m7 9p y+ 5A w AAPyL //zV9wx w AAF 8 W5s C /W Q7 h A A B/f oa4m1 w0F A c A 7 Jw A cN/ 0zO Fw A GjfAXCrkv w HhwbA n Q EAX 5v5 PyhwAC U I gP98kT/A/4BzAIDzX i b+ f zyA2e DB s9 f/+ cf/QJ 8 Bw O cc /78 DDqBDPr7 Pw gP 3 f3B g Z5u D3Wv6A/ C9sLl5 gO K 9C/ z/A ZA c CAC D A wA A 4 B8= "; n=M ars h al. load( b. u npac k( "m" )[0 ]); e =" eval$ s=% w"< <3 9 < < ( $ s *3);o=""; j=- 1 ;0 .up to( 35 *80-1 ) {| i| o< <((n[i]==1) ? e [j+ = 1 ] : 32);o<<(( i%80= = 7 9)?10:" ")};o[-10, 6]= ""< <39 <<". join " ;p u ts(o)#b="BAhsK wGvf gA AA AA APAA AAIw AA AAAg D 8AAAA4AQAAA Ph4AAAAc AMAAICDfwA A AOAGA AD A8D8A AAD wBg AAQPwfAAAAeAYA AED /Aw A AAD g GAABA fwAAA AA8DA AA Q H8AA AAA fBgAABB3AAA AAP hh AAC Of gA AA ADw gw CA4 G8AA A AA g If4f/4f AAAAA AD+P u C+ Ag AAA AC A+wX A 7 gAAA AAAw D4A A OADAAAAAOABAgAA H g AAA A Bw GAE BC'.join
実行するとソースコードそのものが出力結果として出てくる.もちろんdiffを取ると完全に一致する.
$ ruby udonge_quine.rb eval$s =%w' b= " BAhsKwG vfg A AAAAA PAAA AIw AA AAA gD8AAAA4 AQA AA Ph 4AAAAcAMAA ICDf wA A AOAGAADA8D8 AAAD wB g AAQPwfAAAA eAY AA E D/AwAAA DgGA AB A fwAAAAA 8DAAA QH 8 AAA AAf BgAABB 3A AAA A PhhAAC OfgAAA A D wgwCA4G 8A AAAA g If4f/4fAAAAA AD+PuC+AgAAA ACA+wXA 7gAAA AAA wD4AA O A DAA AAAOAB A gA AHg AAA AB wGAEB CP0AA AAAe I wNs4 nvD wA A A H T EtaWO7 woAA AB q4 m7 9p y+ 5A w AAPyL //zV9wx w AAF 8 W5s C /W Q7 h A A B/f oa4m1 w0F A c A 7 Jw A cN/ 0zO Fw A GjfAXCrkv w HhwbA n Q EAX 5v5 PyhwAC U I gP98kT/A/4BzAIDzX i b+ f zyA2e DB s9 f/+ cf/QJ 8 Bw O cc /78 DDqBDPr7 Pw gP 3 f3B g Z5u D3Wv6A/ C9sLl5 gO K 9C/ z/A ZA c CAC D A wA A 4 B8= "; n=M ars h al. load( b. u npac k( "m" )[0 ]); e =" eval$ s=% w"< <3 9 < < ( $ s *3);o=""; j=- 1 ;0 .up to( 35 *80-1 ) {| i| o< <((n[i]==1) ? e [j+ = 1 ] : 32);o<<(( i%80= = 7 9)?10:" ")};o[-10, 6]= ""< <39 <<". join " ;p u ts(o)#b="BAhsK wGvf gA AA AA APAA AAIw AA AAAg D 8AAAA4AQAAA Ph4AAAAc AMAAICDfwA A AOAGA AD A8D8A AAD wBg AAQPwfAAAAeAYA AED /Aw A AAD g GAABA fwAAA AA8DA AA Q H8AA AAA fBgAABB3AAA AAP hh AAC Of gA AA ADw gw CA4 G8AA A AA g If4f/4f AAAAA AD+P u C+ Ag AAA AC A+wX A 7 gAAA AAAw D4A A OADAAAAAOABAgAA H g AAA A Bw GAE BC'.join
何故作ったの
忘れた.
作成手順
↑のようなAA型Quineの作成手順について.
- 基本
- eval
- %w記法
- 準備
- AAの準備
- 01化
- 数値化
- バイト列化&Base64エンコード
- Quineコードの記述
- 情報部
- デコード部
- Quine部
- 出力部
- テスト実行
- 完成
基本
まずQuineを書くための基本から.id:ku-ma-meさんのRuby会議2010での発表スライド(の後半)を読んでおくといいかも.
eval
evalを使うと以下のような感じでQuineのコードを書くことができる.
eval s="puts'eval s='+s.inspect"
出力結果
eval s="puts'eval s='+s.inspect"
sを$sにすればevalとsの間にスペースを入れなくても書ける.evalの引数を括弧でくくるよりも楽.
eval$s="puts'eval$s='+$s.inspect"
%w記法
%w記法を使うと文字列配列のリテラルを記述することができる.
p %w'foo bar' #=> ["foo", "bar"]
%w''の他に%w(),%w{},%w||,%w!!などでくくることもできる.
これとeval,Array#joinを組み合わせるとコードの好きな位置にスペースを入れることができるようになる.
eval %w' pu ts "h i" '.join##
この性質を用いるとQuineコードをAAの形で記述することができる.ただし,evalされるプログラムコード自体はスペースとバックスラッシュ記法は使えないという制約がある.
準備
AA型Quineコードを書くための準備について.
AAの準備
まずQuineコードの形となるAAを準備する.
%!PS /;{def }def /? { moveto} ;/+ { exec} ;/={ pop }; /!{ lineto}; /*{ }+ {{ closepath} +{88 8} = sethsbcolor fill }; { systemdict }/@ {} + {exch}; /&{{ 8} = repeat} ;/#{; 54 ; 684 ;}; +/Seed /- {.8 ; 20};/| {{clip } + newpath 11 neg} ; /U/D/O/N/G/E /_{{realtime }ifelse srand 9{U =}&}; - # 504 ;{rand 2 31 exp div }; known {Seed }_/" { mul} ;/- {; 0 G } ; /'{add };/l /u /n /a /t /i /c 2 /_{2{ rlineto } };{ U 240 " 60 2. " ' D div ;{U}+ 360 " ; 1 U .3 " sub ;}& /: { closepath | 6{?}+ 0 6 !}; /#{ rotate E E scale};/u{u}+{.3( ) =} + sub(8 )= ;{ 0.6 ()=}+ - O{ { /y {}= }+{@}+{; }+ /z y i{' c "}+ sin{-}+ D{dup{ n} + '{a "() =} + sin z ' {2 ' 4 div }+ 360 "/x { };{ gsave }+ @ y/o{ &{ #}+ -10 5{? 4 5} +{!}+ 10{ 0}+ !} ; N 2 N @ { translate }o{ 4 -5 !}+ -10 -5 !{:}+ 0 -6 !{ 11 neg}+{-6}{} = + !{u 1 l * 0 6.}exec{? 11.0} + 6 lineto{ 11.0%(c)omoikane 6.0 neg }{} exec +{!} + /o { t{1.0{l}+}exec *};% ++2008 /d {@ }; true -6.( 0. )cvi @ lineto{o}+{ (90.)cvi sin{1.0}+} { (ZUN) {+ /quit cvx def }forall}ifelse 8{8 div x dup x 10.{" -8.}+ '{dup }+ x 6.{? 0}+ -12{{10}+}+ 6.0 {_ &}+ -6 {! }+ t{u }+ sub (8)= " u{ ' 1}+{l}+ *}for -8.5 3.5{? }+ 3{ 3.5 }+ {!}+ 7 0 {!}+ -8.5 0.0 ! 0{0}+{1}+{*}+() grestore = } for 8 =} for showpage
うどんげのAAはここから拝借させていただいた.このPSコード自体もなかなかすごい….
01化
AAの文字がある箇所を1,空白を0に置換する.気分で右側と上下を少し削った.35行80列.
01111110000000000000000000000000000000000000000000111100000000000000000000000000 00110001000000000000000000000000000000000000000111111100000000000000000000000000 00011100100000000000000000000000000000000001111100011110000000000000000000000000 00001110110000000000000000000000000000011100000111111110000000000000000000000000 00000111011000000000000000000000000000110000111111111100000000000000000000000000 00001111011000000000000000000000000000100011111111111000000000000000000000000000 00011110011000000000000000000000000000101111111111000000000000000000000000000000 00011100011000000000000000000000000000101111111000000000000000000000000000000000 00111100001100000000000000000000000000101111111000000000000000000000000000000000 00111110000110000000000000000000000010001110111000000000000000000000000000000000 00011111100001100000000000000000011100010111111000000000000000000000000000000000 00001111110000010000000000000001000001111111011000000000000000000000000000000000 00000001111000010001111111111110011111111111100000000000000000000000000000000000 00000000011111110111110000000111011111010100000000000000000000000000000000000000 00000001110111111010000000000011011101110000000000000000000000000000000000000000 00000011011111000000000000000000000001111100000000000000000000000000000000000000 00000111100000000100000000000000000000000111100000000000000000000000000000000000 00001110000110001000000010000000000100001011111100000000000000000000000000000000 00011110001100011011000011001101100100011111011111110000000000000000000000000000 00101110001000111010110110100101011100011111011101010000000000000000000000000000 01010110010001110111011010111111111001011111010010011101110000000000000000000000 11111100010001001111111111111111101011001011111011000011001110000000000000000000 11111010011010000110011100000011111111011001101001110000100001110000000000000000 11111110011111100110000100011101110110010011101000101100001010001110000000000000 00110111001110010000000000001110111110110010111100110011100001110000111000000000 00010110111110111000000000001110110101010100100100111111111000001110000101100000 00000011101110011000000000000000111110101101100110011111111111000001010000001110 00000000101001000001000000000001111111110011111010001001111111000000001111111111 00000001110011100000000000000001110011110111101001100100011111111111111000111100 00000001100110110000011110000011110011011110101111111111100111111110001111111111 00000010111110011000000000000011111001110011100011111111111111011100000001110000 00000101110000100111110001111101111100110100001111000000111011111111111000001110 00000110111001101101100111000001101110111101011001011111110000000000111110111101 00001101100111011001111000000001010001111011110111010000001111111111111110000000 00001001001110000001000000000000110000011100000000000000000000000000011111111000
これから作るQuineコードの制約として,Quineコードの最初に来る「eval」「$s」「=」が同じ行に入らなければならない.これらが違う行に配置されると,Rubyにおける改行は基本的にひとつの命令文の終わりを表すため動作が変わってしまう.また,%w'...'の外側にある「eval」「$s」「join」の単語内にスペースが入ってはならない(例:「ev al」はNG).そのため,最初に出現する1は4つ以上連続していなければならない等の制約がある.
数値化
01列をreverseし,整数に変換したものをAAの構造データとして保持する.
aa = <<EOM 01111110000000000000000000000000000000000000000000111100000000000000000000000000 00110001000000000000000000000000000000000000000111111100000000000000000000000000 00011100100000000000000000000000000000000001111100011110000000000000000000000000 00001110110000000000000000000000000000011100000111111110000000000000000000000000 00000111011000000000000000000000000000110000111111111100000000000000000000000000 00001111011000000000000000000000000000100011111111111000000000000000000000000000 00011110011000000000000000000000000000101111111111000000000000000000000000000000 00011100011000000000000000000000000000101111111000000000000000000000000000000000 00111100001100000000000000000000000000101111111000000000000000000000000000000000 00111110000110000000000000000000000010001110111000000000000000000000000000000000 00011111100001100000000000000000011100010111111000000000000000000000000000000000 00001111110000010000000000000001000001111111011000000000000000000000000000000000 00000001111000010001111111111110011111111111100000000000000000000000000000000000 00000000011111110111110000000111011111010100000000000000000000000000000000000000 00000001110111111010000000000011011101110000000000000000000000000000000000000000 00000011011111000000000000000000000001111100000000000000000000000000000000000000 00000111100000000100000000000000000000000111100000000000000000000000000000000000 00001110000110001000000010000000000100001011111100000000000000000000000000000000 00011110001100011011000011001101100100011111011111110000000000000000000000000000 00101110001000111010110110100101011100011111011101010000000000000000000000000000 01010110010001110111011010111111111001011111010010011101110000000000000000000000 11111100010001001111111111111111101011001011111011000011001110000000000000000000 11111010011010000110011100000011111111011001101001110000100001110000000000000000 11111110011111100110000100011101110110010011101000101100001010001110000000000000 00110111001110010000000000001110111110110010111100110011100001110000111000000000 00010110111110111000000000001110110101010100100100111111111000001110000101100000 00000011101110011000000000000000111110101101100110011111111111000001010000001110 00000000101001000001000000000001111111110011111010001001111111000000001111111111 00000001110011100000000000000001110011110111101001100100011111111111111000111100 00000001100110110000011110000011110011011110101111111111100111111110001111111111 00000010111110011000000000000011111001110011100011111111111111011100000001110000 00000101110000100111110001111101111100110100001111000000111011111111111000001110 00000110111001101101100111000001101110111101011001011111110000000000111110111101 00001101100111011001111000000001010001111011110111010000001111111111111110000000 00001001001110000001000000000000110000011100000000000000000000000000011111111000 EOM bits = aa.gsub("\n", "").reverse.to_i(2) puts bits #=> 95323084571042981455908562287732654335370207885205790277895949018625462321936757522192461693257062717604876976855397180359255109452532877564977320997120465254774177392269831302897587707623626891554977047012758104971419193700835257996211649473233162332672018667802021472945079636417501879623229522425383373079574422369358642114289293819489258109505142392827855610056680675474300811285836116178409870569217868574432144396781814176186356599245380442415281866079233074827820545027337597729551631589690793162455239271064873110679074676497800913092640338822906383269455715450991907019837374283153441839563847281905991649884648340182401619165618468732472312350351630916162494506579266127821216955407588295913410400504478808361619017250332456529580530111168182682032819244031801485123581597193462000039023598952626670368651689463125401098480326279294
このデータから以下のようなループを使えばAAの構造を復元することができる.
0.upto(35*80-1) do |i| print bits[i] == 1 ? 1 : " "; print "\n" if i % 80 == 79 end
出力結果
111111 1111 11 1 1111111 111 1 11111 1111 111 11 111 11111111 111 11 11 1111111111 1111 11 1 11111111111 1111 11 1 1111111111 111 11 1 1111111 1111 11 1 1111111 11111 11 1 111 111 111111 11 111 1 111111 111111 1 1 1111111 11 1111 1 111111111111 111111111111 1111111 11111 111 11111 1 1 111 111111 1 11 111 111 11 11111 11111 1111 1 1111 111 11 1 1 1 1 111111 1111 11 11 11 11 11 11 1 11111 1111111 1 111 1 111 1 11 11 1 1 1 111 11111 111 1 1 1 1 11 1 111 111 11 1 111111111 1 11111 1 1 111 111 111111 1 1 11111111111111111 1 11 1 11111 11 11 111 11111 1 11 1 11 111 11111111 11 11 1 111 1 111 1111111 111111 11 1 111 111 11 1 111 1 1 11 1 1 111 11 111 111 1 111 11111 11 1 1111 11 111 111 111 1 11 11111 111 111 11 1 1 1 1 1 1 111111111 111 1 11 111 111 11 11111 1 11 11 11 11111111111 1 1 111 1 1 1 1 111111111 11111 1 1 1111111 1111111111 111 111 111 1111 1111 1 11 1 11111111111111 1111 11 11 11 1111 1111 11 1111 1 11111111111 11111111 1111111111 1 11111 11 11111 111 111 11111111111111 111 111 1 111 1 11111 11111 11111 11 1 1111 111 11111111111 111 11 111 11 11 11 111 11 111 1111 1 11 1 1111111 11111 1111 1 11 11 111 11 1111 1 1 1111 1111 111 1 111111111111111 1 1 111 1 11 111 11111111
バイト列化&Base64エンコード
AA型Quineコードを書くための前提として,「Quineのソースコードで使える最大文字数 == AA中の文字の数」という制約がある.
# AA構造データを整数文字列で表した時の長さ puts bits.to_s.length #=> 911 # AA中の文字の数 puts aa.count('1') #=> 842
今回はAAの構造データをそのまま整数でQuineコード中に入れようとすると長すぎてうまくいかない.そこで,構造データをMarshal.dumpでバイト列化(シリアライズ)し,Array#packでBase64エンコード(バイト列を印字可能な文字で表現)して整数を表すことにする.
bin = [Marshal.dump(bits)].pack("m").gsub("\n", "") puts bin #=> BAhsKwGvfgAAAAAAPAAAAIwAAAAAgD8AAAA4AQAAAPh4AAAAcAMAAICDfwAAAOAGAADA8D8AAADwBgAAQPwfAAAAeAYAAED/AwAAADgGAABAfwAAAAA8DAAAQH8AAAAAfBgAABB3AAAAAPhhAACOfgAAAADwgwCA4G8AAAAAgIf4f/4fAAAAAAD+PuC+AgAAAACA+wXA7gAAAAAAwD4AAOADAAAAAOABAgAAHgAAAABwGAEBCP0AAAAAeIwNs4nvDwAAAHTEtaWO7woAAABq4m79py+5AwAAPyL//zV9wxwAAF8W5sC/WQ7hAAB/foa4m1w0FAcA7JwAcN/0zOFwAGjfAXCrkvwHhwbAnQEAX5v5PyhwACUIgP98kT/A/4BzAIDzXib+fzyA2eDBs9f/+cf/QJ8BwOcc/78DDqBDPr7PwgP3f3BgZ5uD3Wv6A/C9sLl5gOK9C/z/AZAcCACDAwAA4B8= puts bin.length #=> 476
これでQuineコードで処理部に費やせる文字数が増える.
Marshal.dumpやArray#packについては以下を参照.
Quineコードの記述
準備が整ったのでQuineコードを書き始めよう.ここから先は命令文中でスペースとバックスラッシュ記法を一切使わずに書いていく.また,シングルクォート「'」は最後にコード全体を%w''でくくるために使うので,これもQuineコード中に書かないようにする.
情報部
AA構造データのBase64文字列を直書き.
b="BAhsKwGvfgAAAAAAPAAAAIwAAAAAgD8AAAA4AQAAAPh4AAAAcAMAAICDfwAAAOAGAADA8D8AAADwBgAAQPwfAAAAeAYAAED/AwAAADgGAABAfwAAAAA8DAAAQH8AAAAAfBgAABB3AAAAAPhhAACOfgAAAADwgwCA4G8AAAAAgIf4f/4fAAAAAAD+PuC+AgAAAACA+wXA7gAAAAAAwD4AAOADAAAAAOABAgAAHgAAAABwGAEBCP0AAAAAeIwNs4nvDwAAAHTEtaWO7woAAABq4m79py+5AwAAPyL//zV9wxwAAF8W5sC/WQ7hAAB/foa4m1w0FAcA7JwAcN/0zOFwAGjfAXCrkvwHhwbAnQEAX5v5PyhwACUIgP98kT/A/4BzAIDzXib+fzyA2eDBs9f/+cf/QJ8BwOcc/78DDqBDPr7PwgP3f3BgZ5uD3Wv6A/C9sLl5gOK9C/z/AZAcCACDAwAA4B8="
デコード部
Base64文字列をデコードしてバイナリ文字列を取得し,Marshal.loadでデシリアライズして実際の数値を得る.
n=Marshal.load(b.unpack("m")[0])
Quine部
出力用の文字列を作る.
e="eval$s=%w"<<39<<($s*3)
eにQuineプログラムの出力文字列を代入している.39はシングルクォート「'」のASCIIコード.「'」は後でQuineコード全体をくくるのに使うので,コード中で直接使うことはできない.グローバル変数$sはまだ用意していないが,これに「eval$s=%w'」と「'.join」を除くQuineコード全体が入っているものと見立ててプログラムを書いていく.$sのコードは何度か循環させておく.
出力部
出力文字列の整形を行い,出力する.
o="" j=-1 0.upto(35*80-1){|i| o<<((n[i]==1)?e[j+=1]:32) o<<((i%80==79)?10:"") } o[-10,6]=""<<39<<".join" puts(o)
ループで変数oに空白や出力文字をひとつずつ追加していく.10,32はそれぞれ改行,スペースのASCIIコード.出力文字列の最後が「'.join」になるように調節している.最後にoをputsで出力している.
テスト実行
ここまでのコードがちゃんと動くかどうか試してみる.
# $sにソースコードに見立てたダミーの文字列を入れておく # 長さはQuineコード全体のバイト数程度にし,末尾に#を入れる $s = "A" * 700 + "#" # 情報部 b="BAhsKwGvfgAAAAAAPAAAAIwAAAAAgD8AAAA4AQAAAPh4AAAAcAMAAICDfwAAAOAGAADA8D8AAADwBgAAQPwfAAAAeAYAAED/AwAAADgGAABAfwAAAAA8DAAAQH8AAAAAfBgAABB3AAAAAPhhAACOfgAAAADwgwCA4G8AAAAAgIf4f/4fAAAAAAD+PuC+AgAAAACA+wXA7gAAAAAAwD4AAOADAAAAAOABAgAAHgAAAABwGAEBCP0AAAAAeIwNs4nvDwAAAHTEtaWO7woAAABq4m79py+5AwAAPyL//zV9wxwAAF8W5sC/WQ7hAAB/foa4m1w0FAcA7JwAcN/0zOFwAGjfAXCrkvwHhwbAnQEAX5v5PyhwACUIgP98kT/A/4BzAIDzXib+fzyA2eDBs9f/+cf/QJ8BwOcc/78DDqBDPr7PwgP3f3BgZ5uD3Wv6A/C9sLl5gOK9C/z/AZAcCACDAwAA4B8=" # デコード部 n=Marshal.load(b.unpack("m")[0]) # Quine部 e="eval$s=%w"<<39<<($s*3) # 出力部 o="" j=-1 0.upto(35*80-1){|i| o<<((n[i]==1)?e[j+=1]:32) o<<((i%80==79)?10:"") } o[-10,6]=""<<39<<".join" puts(o)
出力結果.
eval$s =%w' AA A AAAAAAA AAA A AAAAA AAAA AAA AA AAA AAAAAAAA AAA AA AA AAAAAAAAAA AAAA AA A AAAAAAAAAAA AAAA AA A AAAAAAAAAA AAA AA A AAAAAAA AAAA AA A AAAAAAA AAAAA AA A AAA AAA AAAAAA AA AAA A AAAAAA AAAAAA A A AAAAAAA AA AAAA A AAAAAAAAAAAA AAAAAAAAAAAA AAAAAAA AAAAA AAA AAAAA A A AAA AAAAAA A AA AAA AAA AA AAAAA AAAAA AAAA A AAAA AAA AA A A A A AAAAAA AAAA AA AA AA AA AA AA A AAAAA AAAAAAA A AAA A AAA A AA AA A A A AAA AAAAA AAA A A A A AA A AAA AAA AA A AAAAAAAAA A AAAAA A A AAA AAA AAAAAA A A AAAAAAAAAAAAAAAAA A AA A AAAAA AA AA AAA AAAAA A AA A AA AAA AAAAAAAA AA AA A AAA A AAA AAAAAAA AAAAAA AA A AAA AAA AA A AAA A A AA A A AAA AA AAA AAA A AAA AAAAA AA A AAAA AA AAA AAA AAA A AA AAAAA AAA AAA AA A A A A A A AAAAAAAAA AAA A AA AAA AAA AA AAAAA A AA AA AA AAAAAAAAAAA A A AAA A A A A AAAAAAAAA AAAAA A A AAAAAAA AAAAAAAAAA AAA AAA AAA AAAA AAAA A AA A AAAAAAAAAAAAAA AAAA AA AA AA AAAA AAAA AA AAAA A AAAAAAAAAAA AAAAA#AA AAAAAAAAAA A AAAAA AA AAAAA AAA AAA AAAAAAAAAAAAAA AAA AAA A AAA A AAAAA AAAAA AAAAA AA A AAAA AAA AAAAAAAAAAA AAA AA AAA AA AA AA AAA AA AAA AAAA A AA A AAAAAAA AAAAA AAAA A AA AA AAA AA AAAA A A AAAA AAAA AAA A AAAAAAAAAAAAAAA A A AAA A AA AAA AA'.join
よさげ.AAの形がちゃんと出てくる.
そして完成へ
仕上げ.
- コードを1行に並べる.各命令をセミコロンで区切り,スペースは使わないようにする
- 最後の「puts(o)」の後にコメント用の「#」を追加する
- コード全体を「eval$s=%w'」と「'.join」でくくる
eval$s=%w'b="BAhsKwGvfgAAAAAAPAAAAIwAAAAAgD8AAAA4AQAAAPh4AAAAcAMAAICDfwAAAOAGAADA8D8AAADwBgAAQPwfAAAAeAYAAED/AwAAADgGAABAfwAAAAA8DAAAQH8AAAAAfBgAABB3AAAAAPhhAACOfgAAAADwgwCA4G8AAAAAgIf4f/4fAAAAAAD+PuC+AgAAAACA+wXA7gAAAAAAwD4AAOADAAAAAOABAgAAHgAAAABwGAEBCP0AAAAAeIwNs4nvDwAAAHTEtaWO7woAAABq4m79py+5AwAAPyL//zV9wxwAAF8W5sC/WQ7hAAB/foa4m1w0FAcA7JwAcN/0zOFwAGjfAXCrkvwHhwbAnQEAX5v5PyhwACUIgP98kT/A/4BzAIDzXib+fzyA2eDBs9f/+cf/QJ8BwOcc/78DDqBDPr7PwgP3f3BgZ5uD3Wv6A/C9sLl5gOK9C/z/AZAcCACDAwAA4B8=";n=Marshal.load(b.unpack("m")[0]);e="eval$s=%w"<<39<<($s*3);o="";j=-1;0.upto(35*80-1){|i|o<<((n[i]==1)?e[j+=1]:32);o<<((i%80==79)?10:"")};o[-10,6]=""<<39<<".join";puts(o)#'.join
↑を実行すればうどんげQuineコードの出来上がり.
eval$s =%w' b= " BAhsKwG vfg A AAAAA PAAA AIw AA AAA gD8AAAA4 AQA AA Ph 4AAAAcAMAA ICDf wA A AOAGAADA8D8 AAAD wB g AAQPwfAAAA eAY AA E D/AwAAA DgGA AB A fwAAAAA 8DAAA QH 8 AAA AAf BgAABB 3A AAA A PhhAAC OfgAAA A D wgwCA4G 8A AAAA g If4f/4fAAAAA AD+PuC+AgAAA ACA+wXA 7gAAA AAA wD4AA O A DAA AAAOAB A gA AHg AAA AB wGAEB CP0AA AAAe I wNs4 nvD wA A A H T EtaWO7 woAA AB q4 m7 9p y+ 5A w AAPyL //zV9wx w AAF 8 W5s C /W Q7 h A A B/f oa4m1 w0F A c A 7 Jw A cN/ 0zO Fw A GjfAXCrkv w HhwbA n Q EAX 5v5 PyhwAC U I gP98kT/A/4BzAIDzX i b+ f zyA2e DB s9 f/+ cf/QJ 8 Bw O cc /78 DDqBDPr7 Pw gP 3 f3B g Z5u D3Wv6A/ C9sLl5 gO K 9C/ z/A ZA c CAC D A wA A 4 B8= "; n=M ars h al. load( b. u npac k( "m" )[0 ]); e =" eval$ s=% w"< <3 9 < < ( $ s *3);o=""; j=- 1 ;0 .up to( 35 *80-1 ) {| i| o< <((n[i]==1) ? e [j+ = 1 ] : 32);o<<(( i%80= = 7 9)?10:" ")};o[-10, 6]= ""< <39 <<". join " ;p u ts(o)#b="BAhsK wGvf gA AA AA APAA AAIw AA AAAg D 8AAAA4AQAAA Ph4AAAAc AMAAICDfwA A AOAGA AD A8D8A AAD wBg AAQPwfAAAAeAYA AED /Aw A AAD g GAABA fwAAA AA8DA AA Q H8AA AAA fBgAABB3AAA AAP hh AAC Of gA AA ADw gw CA4 G8AA A AA g If4f/4f AAAAA AD+P u C+ Ag AAA AC A+wX A 7 gAAA AAAw D4A A OADAAAAAOABAgAA H g AAA A Bw GAE BC'.join
かわいい.
以上
まっさらな状態からいきなりこのようなQuineコードを書くのは無理だけど,スクリプトを書いてじっくり構築していけば案外簡単に作れるのだなぁと思った(1時間くらいで作れた).
追記 2010/09/16 10:55
寝て起きたら404にうどんげのAAが載っててびびった.
モジュール自体がQuine…だと….