ICFP Contest 2015 参戦記

今年は海外出張中だったのですが,去年,一昨年と同じメンバー iwiwi, imos, sulume, wata, chokudai と参加していました(チーム Unagi)。

開始前

  • 量子チューリングマシンという話に期待が高まる。
  • 暗号は解けない。
  • Cthulhu ということなので『這いよれニャル子さん』で予習しようとするも,アニメの第2期第1話を観たくらいしかできず。なぜ第2期かって,第1期はcrunchyrollになかったから。
  • コンピュータを新しくして,開発環境が入っていなかったので,Java と Mono をインストール。
  • 開始時刻の直前に8時間眠るように睡眠を調整。

1日目 (Lightning)

  • 正六角形タイルでテトリスをしろという問題のようだ。量子はどこへ?
  • 移動のさせかたが特定の列(以下,「呪文」と呼ぶ)になっていると,得点が入る。呪文リストは隠されていて,呪文の得点は Lightning では関係ないが,Lightning 中からスコアボードには影響していて,でも,Final Round ではプログラムに呪文リストを貰える。でも,スコアボードである程度勝っていないと,Final Round に進めない。呪文にどのタイミングで取り組むかは謎だった。
    • 呪文に取り組むかは謎だったのだが,いろいろな事情で,早めに呪文当てをすることになる。
  • 開始直後,コンテストサーバー側での採点にバグがあり,早くも優勝ペース(参考: http://twitter.com/imos/status/629653593532928000)。
    • このバグに気づいていたチームは Unagi と Rabbit House だけだった気がする。
  • 例年の通り,wata, chokudai がマラソンマッチ的なことを担当し,imos, sulume がチーム内スコアボードとか複数のソルバーの統合とかの環境を担当。
  • ゲームの仕様で与えられる座標系がやばいので,まともな座標系に直す。ただし,ゲーム中で列を消したときの落下処理はやばい座標系に従うので,整合性をとる必要がある。仕様の (x,y) を (2*x+y%2,y) にうつすと直交座標になり(正規直交座標ではない),上記の問題とも相性が良さそうなので,それを使うことにした。
    • この判断が正しかったかは自信ないが,チームメンバーはあまり混乱してなかったようなので良しかな。変なルールがなければ,60度の斜交座標を用いるのが普通だと思う。
    • しかし,上のコードでは y が負のときにバグ。Haskell で rem, quot; div, mod が分けられてることへの感謝の気持ちを忘れてしまっていた。
  • 早くも自分の仕事がなくなりつつあるが,Lightning 後のために,呪文の詰め込みかたなどを考えることにする。
    • ルールでは同じテトを過去と同じ位置にするような移動が禁止。降ってくる個数が決まっているため,下(というか,Hex なので左下60度と右下60度)にあまり移動しないことが大事なので,左右で戻りたいときは回転してから戻すとか。
  • やはり仕事がなくなりつつあるので,imos, sulume がまだ手をつけていない visualizer を作りはじめる。
  • 勉強もかねて,GLUT か GLFW の Haskell 用バインドを使おうとしたが,無駄にコピペコードになりそうなのと,他の人が使うときに cabal でハマったりする可能性が怖かったのであきらめて,JavaScriptCanvas でやる。
    • JavaScript はそれなりに書いていた時期があったが, .length() でエラーが出て「これだから配列かどうかすら分からない言語は」と腹を立てたり(.length が正しいので筋違い),それを直したら,今度は Math.cos(i*Math.pi/3) などと書いていたところでエラーが出て,「Math.PI が正しいとか馬鹿じゃないの? なんで関数が副作用がないかには気にしないくせに,double型が定数かどうかにはこだわるんだよ」と腹を立てたりした(これは C言語で PI だったレガシーを背負ってしまったとしか理解できていない)。
  • 遠隔参加なので,起きていても全部の会話が拾えていることもないし(ネット回線やマイクの位置の問題),オンサイトだった去年までと比べるとチームの状況があまり把握できない。
    • 「スコアボードが修正されてから,Unagi はなかなか解答を送信しないな。潜伏戦略なのかな」と思って聞いたら,「1位です」と返ってきて,自分がスコアボードの更新をしてなかっただけだと気づいたり。
  • 今年も wata, chokudai の力が発揮され,割と良い感じの成績っぽい。1位のチームは Lightning で得点にならない呪文で稼いでいるっぽいし,Lightning 部門勝利もあるな,という感じで初日は終了。

2日目

  • 日本にいるチームメンバーとの睡眠のタイミングを合わせられなくなってくる。
  • iwiwi 呪文の解析を頑張っていたので実際の呪文がいくつか特定されている。
  • 呪文まわりの戦略について chokudai と話す。"ia! ia!" は重複させられるので強そうに見えるが,"r'lyeh" の方が下への操作をあまり入れないので強い。ただし(60度対称で)回転できないテトだと結局 "ia! ia!" するしかない。
  • imos, sulume が書いている C++ シミュレーターを少し改造するが,どうビルドすれば良いのか分からない。GitHub の更新を検知して自動ビルドの結果が Slack に流れてくる仕組みがあったので,一発書きを commit, push した。
    • あまり良くないんだけど,担当の2人は寝ているし,破壊的に変更していないはずだし,push したらビルド通ったっぽいしまあいっか,みたいな。
  • JavaScript で書いたビジュアライザを,ゲームプレイに対応させていなかったところ,C++ シミュレーターの側にゲームプレイのアスキーアート出力がついた。自分がこれ以上 JavaScript で何かしようという気がなくなる。
  • テキスト表示を見ていると正六角形で美しく出力する意味があまりないことに気付く。テトが連結とかいう制約もないしグラフィカルにやるにしても円で十分では? wata, chokudai が自前のテキスト出力で大丈夫そうにしていたのも納得。
  • 呪文候補のローマ字列を入れると,対応する操作を矢印(←→↙↘↻↺)の列で出力するだけの簡単なプログラムを書く。矢印の列を Slack に貼ったら斜め矢印だけ絵文字に化けた(斜め下移動がある意味目立つべきといえばそうなので,偶然だが分かりやすかったとも言える)。
    • 例:↙↘↘↙↙↺↘↙↘↺↺→↘↙↺↘↻←↘→→↙↘↻→↙↻↘→↺↙↺↘↙↺↘↺↙↙↺↺↘↻↻→↙↘↙↘↙←
  • スコアボードで呪文を18個中9個も使えているチームがいることに驚く。
  • iwiwi が取り組んでいた呪文当てがツール化されて,誰でも使えるようになった。呪文を含む死なないようなプレイを適切な問題番号で探し,それを submit する仕組み。
  • ICFP 2015 accepted papers のタイトルに含まれる単語を iwiwi ツールにどんどん貼り付け。しかし,当たらない。
  • 呪文当てをする唯一の手段が公式スコアボードだったし,分かっている呪文の範囲での点数は自己採点できるため,必然的に「潜伏」戦略になる。
    • AIと自前のシミュレーターの採点が同時にバグっているという可能性を排除するために,「潜伏解除」もした。
  • どうせ "2015" とか "icfp" とか入っているんじゃないの? と思うものの,どちらも左右に行って戻る連続した移動があり,そこでテトを切り替えないと反則なので,死なない手順を自動で見つけるのは難しい。手作業で手順を作ったが,呪文ではなかった。残念。
  • 日本にいるチームメンバーとの睡眠のタイミングを全然合わせられなくなってくる。

3日目

  • 寝ている間に,結構,呪文が判明している。Twitter でヒント祭りがあったらしい。
  • 寝ている間に「全完」目標になっていた。
  • 内部スコアボードでは圧勝しているが,全問題で1位にする気らしい。
  • AI の動作をながめて「複数列消しを狙う方が良いのでは?」と言ってみたが,見当外れらしい。
    • そのときはあまり構ってもらえなかったが,冷静に考えて Lightning でないと本当にそう。盤の横幅が広くなっても,列を消す得点は変化しないし,複数列消しを待つために積むと呪文があまり入らなくなる。
  • web と twitter しか見ていなかったものの,IRC にもヒントが結構流れているらしいという話。IRC は入っていないとログが見れない。ログが置かれている場所があるらしいがつながらない。
    • それもそのはず,去年の ICFP Contest で使ったときのままの channel topic に「ログが置かれている場所」情報が放置されていたため,つながったとしても1年前のログだったのだ。
  • 公式 twitter 初期の謎の文字列をプロットしてみると,やたらなめらか。楽譜っぽい,というところから解けた。というか,テトリスであることを知っていたので,解けた。解答を確信したのち,文字の選び方を合理化するためには rot13 するんだな,と分かった。順番が逆。
    • 解けてしまったことで,これはテトリスである情報しかないことが判明。呪文探しには役に立たない。(それでも,rot13 とか Ceaser とかを iwiwi ツールに投げていた。)
  • 「Problem 24 の街があやしい,本当に Vancouver(注:ICFP 2015 開催地)か? クトゥルフ的な街でないのか?」という疑問があったため,Vancouver の名所を画像検索。一番あやしげな塔に似た建物は発見。おそらく海側からの写真をもとに Problem 24 を描いているのだが,ちょうどその向きの写真は見つけられなかった。
  • 「全完」を諦め,浮上。Twitter でも報告,を自分だけしそこねた。スコアボードで圧勝しているので,IRC でも話題になるかと期待したが,そのころの IRC は過疎っていた。
  • そういうことで,呪文探しは18個中16個見つけた時点で終了。自分の戦果は,"cthulhu fhtagn!"(チームメンバーは感嘆符を入れては試していなかった)と,最大51文字とアナウンスされていたやつのもう1つの方。どちらも51文字なのはちょっと驚き。
  • あと2時間くらいで終了というところで眠くなって脱落。日本の音声をイヤホンに入れたまま寝るみたいなことをしていたので,なんか終了直前に起きた。

終了後

  • チームメンバーの打ち上げ映像。いいなあ。
  • 未発見の呪文の片方は謎解き力が足りなかったが,もう片方は完全に無理だった。意味不明な 10^63 は調べるべきだった(2^63の誤植だと思ったのが運のつき感もある)。