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