Gene listの残りのページを見る

2013-05-02

ICFP2007の続き。85ページのField-repairing Fuunsには遺伝子を有効にする方法が書かれている。Adapterとういものを使えば簡単にできるとのこと。緑ゾーンの遺伝子を呼び出すには、IFPICFPPCCCというマーカー2つの間のDNAを先頭にコピーして、続けてオフセットを整数にエンコーディング、続けて遺伝子のサイズ、とすればいいらしい。呼び出し終わるとDNAの先頭から緑ゾーンのアダプタの起動までは復元されるとのこと。

なにか情報を渡したい場合には青ゾーン(IFPICFPPCFIPP)の先頭に置くこと。

例の、整数42を青ゾーンの先頭にコピーするprefix、IIPIFFCPICCFPICICFPCICICIICIICIPPPCFCFCFCCCCCCCCCCCCCCCCCICIIC は、デコードすると

| Pattern | (?"IFPICFPPCFIPP") | | Template | {0_0}ICICICIIIIIIIIIIIIIIIIIP |

となる。パターンで青ゾーンを探して、テンプレートで青ゾーンまでをそのままコピー、42をエンコードしたものを挿入する、という内容。

真偽値をコピーするprefix、IIPIFFCPICCFPICICFPCICICIICIICIPPPPIIC も同様に、

| Pattern | (?"IFPICFPPCFIPP") | | Template | {0_0}F |

となる。

緑ゾーンからオフセット1234にある500の遺伝子を有効にするprefix、IIPIFFCPICCFPICICFFFIIPIFFCPICCFPICICFFFIICIICIICIPPPCFCCFCFFCCFICCCFCFFFFFICIPPCPIIC は、

| Pattern | (?"IFPICFPPCCC"(?"IFPICFPPCCC")) | | Template | {0_0}ICIICICCIICPIICICCCCCP{1_0} |

で、パターンでアダプタの2つのマーカーIFPICFPPCCCを探して、テンプレートでオフセット1234=0b010011010010、サイズ500=0b111110100をアダプタに渡している。

試しになにか動かしてみたいと思って、42ページのGene listに書かれている、appletree(オフセット:0x3c870e, サイズ:0x00372b)を呼び出してみようと、IIPIFFCPICCFPICICFFFIIPIFFCPICCFPICICFFFIICIICIICIPPPCFFFCCCCFFFCCCCFCCFFFFICFFCFCFCCFFFCFFICIPPCPIIC (Pattern: (?"IFPICFPPCCC"(?"IFPICFPPCCC")), Template: {0_0}ICCCIIIICCCIIIICIICCCCPCCICICIICCCICCP{1_0}) というprefixを渡すと、出力されるRNAの最初の5200くらいで林檎の木が左上に描かれた!

なにか引数を与える遺伝子でも試してみたい、けどGene listには遺伝子の名前しか書かれてないのでなにを有効にしたらいいのかわからないなぁ。Gene listは14ページ中の1ページ目だけなので、残りの13ページを見るにはどうしたらいいのか。先頭のサイズ24のAAA_geneTablePageNrというのが怪しそう、だけどどうしたらいいのかわからなかったので、いんちきしてググってICFP2007 (6) gene table - Sim’s blogのページを見つけた。AAA_geneTablePageNrの中身を書き換えてやれば他のページが見れるらしい。じゃあっつって、修理ガイドの42ページを見るための「(?"IFPCFFP")IIIIII, {0_0}int(42)」のパターンとテンプレートに緑ゾーンを探してオフセット0x510(実際には、マーカーのサイズ13を引く必要がある)、サイズ24を書き換えるコードを追加したが、うまく動かない。位置を調べてみると、IFPCFFPはDNAの先頭から14860の位置、緑ゾーンIFPICFPPCFFPPは13615からなので、緑ゾーンの先頭のほうが前にある。なので先に緑ゾーンを探すようにしてみたが、それでも動かない。なんでかなーと考えたら、13615+0x510(=1296)-13=14898で、IFPCFFPマーカーより後ろにある。なのでどちらにしてもサーチに失敗してしまっていた。ここはおとなしく参照先のページのように、IFPFIPを探すように修正してみるとめでたく他のページも表示されるようになった。

他のページを見るためのprefixを生成するツール:

#!ruby
# asnat, protectはドキュメント通り

GeneTablePageNum = 42

def intcode(x)
protect(1, asnat(x))
end

def skip_length(n)
"IP#{asnat(intcode(n).length)}P"
end

def search(dna)
"IFF#{protect(1, dna)}"
end

def ref(n, l)
"IP#{asnat(l)}P#{asnat(n)}P"
end

page_no = ARGV.shift.to_i
puts (# Pattern
"IIP#{search("IFPCFFP")}IIC#{skip_length(GeneTablePageNum)}" +
"IIP#{search("IFPFIP")}IIC#{skip_length(page_no)}IIC" +
# Template
"#{ref(0,0)}#{intcode(GeneTablePageNum)}" +
"#{ref(1,0)}#{intcode(page_no)}IIC")

こいつに1〜13を与えて出てくるprefixで、2ページ〜14ページのGene tableが出力される。