先制 hello, world 最後の提出コード

はじめに

先制 hello, worldに参加しました - ange1のブログの続き、CodeIQで開催された「先制 hello, world」というコードバトルについてのお話です。

先制 hello, world 全試合に詳細が公表されましたので、自分の最終提出コードについてネタバレします。

コード

…これ見ただけだと、プログラムって分かりませんが、我ながら。一応Perlコードです。
分解すると、次のような構成になっています。

e . "文字列" * s!!コード!ee

ベアワード ( 文字列として扱われる ) の e と、""でクォートされた文字列・s演算子 ( デリミタとして、/ の代わりに ! ) の乗算 (*) の結果との文字列結合 (.) を行う、ということになりますが、この評価結果自体に意味はありません。
重要なのは、s演算子の中身です。文字列置換の機能を持つ s演算子に空のパターンを指定していることで、必ずマッチが発生し、かつ e オプションを ee と重ねることで、コード部分が二重に eval されます。つまり eval(eval(コード)) が実行されるのと同じこと。
※その結果、実際に置換が行われて、デフォルト変数$_が書き換わるのですが、書き換わった結果にはやはり意味がありません。

という事で、このコード部分を取り出してみます。

q^Y@@GF~Y@##KYF@_#`bZ#222j`)2@2#b~^ ^ q*)2))2Y)2FF&)2))F@@2F^^]F@^]2^G@Y*
( q^文字列^ ^ q*文字列* )
→ print'preemptive "hello, world"'

これはMinority's hello, worldで見られた文字列のxorですね。q^~^ や q*~* は文字列のクォートですから、間に挟まれた部分が xor されまして、結果print文に化けるという寸法です。xorで望みの文字を作る組み合わせは幾つもありますから、文字の組合せ等々考えるのに手間取ってしまったのは痛かったですね。

選択した文字

Brainf**kと違い、攻撃・防御がそこまで明確に分かれるわけではないですが、次のような感じで考えました。

  • 攻撃:e."空白)]}<2 という先頭の9文字

    • Brainf**kの時とほぼ同じ考え方ですが、防御も兼ねた e も追加しています。
    • あと、対Brainf**k用に . を一応入れてまして。もしかしたら +- の防御を優先していたら2文字目でも間に合うかな…と思ったのですが、やはり上位陣に対しては甘かったようですね。ちなみにPerlの場合、小数点として . をいきなり打つこともできました。.2 とか。( 0.2 と解釈される )
    • < は首位のBashを意識して。ヒアストリング開始の <<< を刺せるかと思ったのですが、echo~|tr で躱されていますね。ここら辺、やっぱり精査が足りなかったと反省です。
  • 防御: e)2*

    • e は、s!!~!ee の形を使う事からも、防御兼用として選んでいます。
    • 後、閉じ括弧の )、これはむしろ防御用として、xor の片割れに積極的に選びました。
    • 同様に 2 も多用したのですが…。Rubyを中心にして、この 2 が刺されてますね。ちょっと甘かったかも知れません。
    • *は少ししか使ってませんが、一応。
  • お祈り用: その他

    • まあ xor で難読化してるので、という事で。

最後に

まあ、優勝を狙うならやはりBrainf**kをbrush upするべきだったんじゃないの、とか、Bashが強いの分かってるなら便乗する手もあったのでは、とか、色々ご尤もな指摘がありそうなのですが。楽しめたので良かったかな、と。膨大なコードと対戦結果をまとめられた出題者の鍋谷さんも、他の参加者の方々もお疲れ様でした。