ICFP Programming Contest 2011に参加した

Home

しばらく前からICFPCでチームを組みたいと漏らしてはいたんだけど、実際にICFPCでチーム戦をしたことのある同じ職場のF氏からの誘いで参加することに。今回、初めてチームを組むことができてとても楽しかった。得難い経験でもあった。…けど、反省点も多数ある。因みにチーム人数は5人。
一日目。午前9時から問題を読む。午前10時から仕事なので、一旦止める。午後7時ぐらいから再開。結果的に、この半日は痛かったかも。

自分はとりあえずシミュレータを書くことに。ざっと頭で構成を練る。このときはまだきちんとルールを把握していなかった。これが後々の失敗の原因に。

最初に考えたのは抽象クラスCardを作って実際のカードはそこから派生させて、カードの保持はCard*やvectorで持たせ、カードをapplyする純粋仮想関数を作れば良いんじゃね? と考えて早速実装。メモリについてはポインタで全部持たせて繋げるだけだし、無限ループも検出するだけで済むし、メモリも使い捨てで問題ないと思っていた。card->apply(card)な感じで。

しかし、ある程度実装したところで、Sやgetなどはポインタを繋げて終わりというわけには行かないと分かり、深いコピーが必要となることに。それでもなんとかなるかなと試行錯誤したけど、巨大なメモリリークが発生したら面倒だし、後々メモリ関連でデバッグするハメになるのは時間が厳しいコンテストではキツイと考えて、全て実体で持たすように変更することにした。これが一日目。正直この一日目は自分のミス。

朝方帰って一眠りした後、昼過ぎに戻って来てスクラッチから書き直し。とにかく動くことが重要だと考えて、LL的な書き方にした。一応4時間ぐらいでbuggyだけどなんとなく動くものに。しかし、とても汚い。LL的な書き方をしたときはリファクタ必須の場合が多いので、動くのを確認したら書き直すつもりでいた。ただ、思ったよりもデバッグに時間がかかり、メインプログラマのN氏にコードを渡した。この時点であまり頭が回らなくなっていたのだけど、とりあえずしばらくいじって適当な区切りで一旦帰宅。

で、一眠りした後に戻ってみるとN氏によるリファクタが入っていてとても読みやすいものに。当のN氏は帰宅して休んでいるとのこと。一通り読んで、一部デバッグした。この時、無限ループ対策やzombieのapplyが施されていなかったので付け加えた。あといくつか変更した覚えがあるけど、詳細は覚えていない。というのも、コミットしようとしたら戻ってきたN氏により既に変更されていたので、コンフリクトしたコードはお蔵入り。この時に無限ループ対策が漏れた。これも失敗だった。

後はシミュレータから得られる情報で統計を取り、向こうの動きを予測して潰すなんてことをするつもりだったけど、最後までシミュレータにバグが残ったままになっていたようで、作ったコードは実践では使われないまま、コンテスト終了。結局、自分自身を回復しないバグが残ったままだった。余談だが、コンテスト終了後、一部修正したら回復するようになったけどそれがほんとうに正しいかどうかは検証していない。

コーディング技術が高いこともあり、多くのコードをN氏が負担してしまったが、これはチーム戦としては方針ミスだったと思う。実際、シミュレータについては同じ部分を修正したりしてこちらの時間も無駄になった。やはり、意志の疎通がうまくできてなかったのではなかろうか。本当は途中で進行状況の報告などがしたかったけど、みんながそれぞれで集中していてあまり邪魔を入れられたくないオーラが出てた(ように思う)。

ただ、メインのコードじゃないというだけで戦術担当のF氏以外は皆が結構書いていたと思う。スレッドを使ったデバッグ用プログラムや解析用・検証用のスクリプト等々。ただ、時間がなかったせいでそれらも十分には利用されなかったは残念だった。それでも、カードのグラフィックの一部の色合いがおかしいというだけでJavaで解析していたりしたんだから、大したものだと思う。

あと、環境が悪かったのは否めない。職場での作業だったけど、冷房は切れているし、寝る場所やシャワーなどもあるわけじゃない。しかも、それぞれが好きな時間に休んだり帰宅したりしたので、連携も取りづらかった。来年は温泉宿を取って快適な環境でやろうという案が上がっている。是非実現したい。

個人的なところでは、コンテスト前日に2時間しか寝ていないとか酷すぎた。原因はノートPCのVMDebianを入れようとしたため。というのも、自宅の回線が1.5MのADSLのためか、途中で止まったり、インストールされないまま終了したり、3回ほど入れ直したから。結局、入らなかったし。仕方が無いので、職場に来て勝手に放っておいたところ、ちゃんとインストールされた。初めからこうしておけば良かった…。

最後に個人的にしたほうが良かったと思うことを書いてみる。

まず最初にコードの部品化はしたかった。もちろん部品同士は疎に繋がっている。それぞれのコードが密に繋がっていたりすると、分担が非常にやりにくい。その一部だけ取り出して検証しようにも難しくなる。あとは、インターフェイスの共通化。これは最初に皆で決めておく。何を作ってどう繋げるか。それさえ決めておけば、それぞれがばらばらに作ったって、どれでも使えるし、より良いものを選択できる。それに、後で実際に使うときにどう使えばいいかすぐに分かる。

今後のためにも反省会は開いておきたいな。