ref: https://github.com/mame/radiation-hardened-quine
放射線はメモリエラーを引き起こすらしいです。そんな放射線が飛び交う過酷な環境でも、できることなら Quine したい。
ということで、プログラム内の 1 文字をランダムに消しても元のプログラムを出力する、なんともロバストな Quine を書きました。*1
何を言っているかわからないと思いますが、こんなふうに動くものです。
# ランダムに 1 文字消すスクリプト $ cat mutate.rb src = $<.read src[rand(src.size), 1] = "" print src # rrquine.rb からランダムに 1 文字消したプログラムを生成する $ ruby mutate.rb rrquine.rb > broken.rb # 壊れたプログラムを実行する (!) $ ruby broken.rb > rrquine2.rb # 元に戻る (!!) $ diff rrquine.rb rrquine2.rb # 一致!
正直書けるわけないと思ってましたが、なんと書けてしまった。Ruby 恐ろしいなあ。他に書ける言語があるだろうか。*2
以下コード。もっと賢い方法があったら教えてください。(追記: GitHub のリポジトリも作っておきました。)
eval='eval$q=%q(puts %q(10210/#{1 1 if 1==21}}/.i rescue##/
1 1"[13,213].max_by{|s|s.size}#"##").gsub(/\d/){["=\47eval$q=%q(#$q)#\47##\47
",:eval,:instance_,"||=9"][eval$&]}
exit)#'##'
instance_eval='eval$q=%q(puts %q(10210/#{1 1 if 1==21}}/.i rescue##/
1 1"[13,213].max_by{|s|s.size}#"##").gsub(/\d/){["=\47eval$q=%q(#$q)#\47##\47
",:eval,:instance_,"||=9"][eval$&]}
exit)#'##'
/#{eval eval if eval==instance_eval}}/.i rescue##/
eval eval"[eval||=9,instance_eval||=9].max_by{|s|s.size}#"##"以下は最初に公開したバージョン。とりあえず動いただけのものなのでいろいろ汚い。
"%\ #{at_exit{eval'(eval q=%(s=%(B%A C{at_exit{ZGQG##G
}}}ABB.rescue x rescue 42##B
Z=GQG##G
instance_Z=GQG##G
Z Z if Z==instance_Z
).gsub ?Z,%[eval]
7.times{|n|s.gsub! (n+65).chr,(n<1?92:n+33).chr}
puts s.gsub ?Q,%[(eval q=%(]+q+%[))#]
$stdout.flush
exit!0))#'##'
}}}\"".rescue x rescue 42##"
eval='(eval q=%(s=%(B%A C{at_exit{ZGQG##G
}}}ABB.rescue x rescue 42##B
Z=GQG##G
instance_Z=GQG##G
Z Z if Z==instance_Z
).gsub ?Z,%[eval]
7.times{|n|s.gsub! (n+65).chr,(n<1?92:n+33).chr}
puts s.gsub ?Q,%[(eval q=%(]+q+%[))#]
$stdout.flush
exit!0))#'##'
instance_eval='(eval q=%(s=%(B%A C{at_exit{ZGQG##G
}}}ABB.rescue x rescue 42##B
Z=GQG##G
instance_Z=GQG##G
Z Z if Z==instance_Z
).gsub ?Z,%[eval]
7.times{|n|s.gsub! (n+65).chr,(n<1?92:n+33).chr}
puts s.gsub ?Q,%[(eval q=%(]+q+%[))#]
$stdout.flush
exit!0))#'##'
eval eval if eval==instance_eval