目次

  1. はじめに
  2. 1日目、会場に到着
  3. チーム紹介をこだわりました
  4. 2日目朝
  5. コンテスト本番
  6. Yes/Noの時間
  7. まとめ
  8. おまけ

はじめに

昨年2024年のICPCに Anonyms として Ayuna + momoyuu + someone_ で出場しました。(前編の再掲)
コンテストからかなり期間が空いての文章の公開ですが、下書き自体はコンテスト直後に書いたものであり、読みにくいと感じた部分を加筆修正してはいますが内容はほぼそのまま公開しています。(これも再掲)
中編だけ読む人のために3人の紹介をすると、だいたいこんな感じ。
Ayuna: レートは青。典型はレート相応に1番弱い。算数と水以下の典型だけで解ける考察問題が得意。自由な発想なら誰にも負けない。直感で解法を当てる。一番元気。雑務と2人が苦手な問題担当。
momoyuu: レートは橙。つよい。めちゃつよい。黄diff以下相当の問題は「自明」と言いながら爆速で通してくれる。橙〜赤diff相当も通してくれることも。数学つよい。競プロのことは何でもやる担当。
someone_: レートは黄。つよい。いつ使えるのか分からない謎知識やデータ構造を知っている。低〜中難易度問題は確実に解いてくれる安心感。説明が上手い。数学つよい。(多分)低〜中難易度と実装担当。
というわけでバランスの良いチームです。 中編は横浜大会当日の話です。 前編では横浜大会までのイベントについての話を書いたので興味があればぜひご覧ください。

1日目、会場に到着

ついに来てしまった12月21日。
どきどき。
駅で3人集合して会場へ向かいました。 私以外の2人は1年前も行っているはずですが、なぜか私が道案内をしました。
1年前、2人は会場に行くときに道に迷ったらしいです。 地図が読めない人は信用ならないので、雑用担当Ayunaが真っ直ぐ連れていきました。
トラブルなく会場に到着。
受付は英語ですが、雰囲気で言いたいことは分かるのでセーフ。
開場とほぼ同時に入場し時間に余裕があり、Tシャツを着たりルールブックなどを読み込んだり思い思いに過ごしました。
途中、写真撮影のスタッフがいきなりやってきたかと思えば「全体の中で君らを最初に撮るよ〜」みたいなことを英語でノリノリで伝えてきて、チームの集合写真を撮影してもらいました。
会場の端にはお菓子やパンがたくさん置いてあり、自由に持っていってよいスタイルでした。 だれさんが取ってこいと言うため雑用担当私はパシられることにします。
とりあえず両手で持てる分だけ、パン3個とお菓子3個を取ってきて一人一つ食べられるぞと思って持って行きました。 席に戻ってもう少し小腹が空いてきたらパンを食べようと思っていたのですが、パソコンを見たりルールブックを読んだりしていたらいつの間にか3つともパンがなくなっていて、私の分のパンがありませんでした。
2人に問い詰めたところ、momoyuuさんが個数を気にせずバクバク食べてしまったみたいです。 これが食い尽くし系ってやつなのか…?
食べ物の恨みを抱えつつも仕方ないので再度パンを取りに行き、私も無事おいしくいただきました。
リハーサルではそれぞれ確認したいことを確認するという感じで、私は自分の担当である最初のセットアップやインタラクティブツールの練習をしました。
あとはclarに何でも投げてよいとのことだったので英語で1つ質問してみました。みんな質問内容がユニークで面白すぎでした。

チーム紹介をこだわりました

リハーサル後は各チームの紹介です。
前に出て話すのも、画面に映し出されるスライドも、冊子に掲載されるチーム紹介の文章も、雑用担当なので私がやりました。
チーム紹介の文章は、アスキーアートのチームが多いということでせっかくなので謎のJavaScriptコードを生成してみました。 紙で配られたのでどんな出力か気になった方は手打ちで試していただく…のも良いのですが我ながら良い出来になったのでこのページの最後におまけとしてつけておきます。
1行あたりの字数制限や行数制限に収めるのがちょっと大変でした。 頑張って文字数や行数を削ったので読みにくさは許して。
ちなみになぜJavaScriptで書いたのかというと、その頃は研究とバイトでJavaScriptを触っていて「オブジェクトってやつ、辞書型みたいに使えて良いなあ!」(この認識は後に悲しみを生む)とハマっていたからです。

2日目朝

discordで起床報告。
だれさんが持ち物のリマインドをしてくれました。
不安になり、玄関でも電車の中でも持ち物を確認しました。
そして無事集合し、2日目も私が2人を会場へ連れて行きました!!

コンテスト本番

開始時間が早まったのはちょっと焦った。競プロの大会だとありがちらしい。
初動では私がPCのセットアップをしている間に、Aをだれさんが、Bをmomoyuuさんが解きました。 セットアップ後、Lを要約し、その後GがインタラクティブだということでGを読みました。
Lはmomoyuuさんが一度提出したものの方針が違うことが分かり諦め。 実況を後日見たのですが、Anonymsが何回も言及されてて嬉しい…
Gは基本的な考え方は読み終わってすぐに出てきました。 実装がかなり重そうということで、だれさんと相談しながら定式化を行い、クエリ回数が足りることも計算して確認。 こちらの方にかなり時間を使ってしまいました。 その間に2人がCEIKを通してくれました。 KのFAありがとう…風船ほしかったな。
Anonymsは他のコンテストでも毎度そうでしたが、初動がめちゃめちゃ早いチームでした。 2位や3位にいた時間もあったらしい。
G問題は実装ミス不可避なので念のためにと大量のassert文を入れながら実装している様子が実況中継に。 デバッグ中だと忘れちゃうので、実装しながら入れていただけです。
テストケースを試そうとすると次々assertに引っかかり大助かり。
ただ、しばらくそれを直したところで致命的な考察の抜けに気づきました。
誤りの内容を説明すると、だれさんがすぐに代替案を提示。 これが正解の解法でした。
私が考えたのは惜しかったなあ…私はすぐにはその正解方針を理解できず、実装をだれさんがやり直すことに。
だれさんも100%自信があるわけではなく、方針を理解できた後はだれさんの代わりにクエリ回数や計算回数が足りることを手計算で確かめました。実況でもずっと一人黙々と紙に向かって何かを書いているところや相談をしているところが映っていたみたい。
そんなこんなしているうちにDを通してくれている。 たしか並行して実装していた問題だっけ?
そしてGのデバッグを少し手伝いつつFを考えます。
2つの直方体の展開図を回転させて繋げたら二次元平面上の円が直角三角形を覆うような半径を二分探索で求められるのでは?と思い計算。 しかしサンプルが合わず困っていた。
その間、粘って粘って、ラスト2分でだれさんが実装の大変なGを通してくれました。大感謝。
こうして振り返ると、私が読んだ問題はFGLと少ないですが、Anonymsの実力と順位からすると勝負を決める問題ばかりでした。 結局1問だけ通りました。

Yes/Noの時間

Yes/Noを初めて生で見ました。
自分のチームが凍結中に問題を通したかどうかはもちろん把握しているので、自分のチームにターンになるとちょっとニヤニヤしちゃう。
みんなもこんな気持ちなのかな。
結果は10位。チームメイトに大感謝。 playoffに行けることになりました。
賞品で英字キーボードをいただきました。
後で、だれさんに「AyunaがいないとGは通せなかった」と言われてかなり嬉しかった。

まとめ

Anonymsはmomoyuuさんだれさんが安定的な戦いをしてくれて、私が謎問題でひらめき大当たりを引くかどうかという構造です。
F問題は3人の中で私が1番取りかかれるタイプの問題ですし、G問題は後から2人に「初動はすぐに思いつかない」と言われたので3人の中では私が適任だったと思います。
私の役割は、貢献できるかどうかは問題セット(特にインタラクティブ問題があるか、パズル問題があるか)に強く依存するので、練習でも自分で提出したコードは0ということも何回かありました。 でも本番で解けて良かった。

私一人の力では辿り着けないところまで来てしまいました。チームメイトには頭が上がらない一方です。ここまで、せめてものという気持ちでチームの誰かがやらないといけない仕事はコンテスト時間中/時間外にかかわらず積極的に引き受けるようにしました。
1月は卒論を頑張らないとなのですが…
2月末からのplayoffはとにかく楽しみたいと思います。 うまくハマればWorld Finalもあるのかな。

おまけ

以下は横浜大会での自己紹介のJavaScriptコードです。 ぜひ下のボタンを押して実行してみてください。 出力する文字列の長さの都合上、スマートフォンでは読みにくいかも。

              
const teamInfo = {
  teamName: "Anonyms",
  university: "Keio University",
  city: "Yokohama, Kanagawa, Japan",
  members: ["Ayuna", "momoyuu", "someone_"],
};

const asciiArtMap = {
  A: ["      _", "     / \\", "    / _ \\    ", "   / ___ \\   ",
      " _/ /   \\ \\_ ", "|____| |____|", "             ",],
  a: ["", "", ",--.", "`'_ :", "// | |,", "'-;__/", ""],
  e: ["", "", " .---. ", "/ /__\\\\", "| \\__.,", " '.__.'", ""],
  m: ["", "", " _ .--..--.  ", "[ `.-. .-. | ", " | | | | | | ",
      "[___||__||__]", "             ",],
  n: ["", "", " _ .--.  ", "[ `.-. | ", " | | | | ", "[___||__]",
      "         "],
  o: ["", "", "  .--.  ", "/ .'`\\ \\", "| \\__. |", " '.__.' ",
      "        "],
  s: ["", "", " .--.  ", "( (`\\] ", " `'.'. ", "[\\__) )", ""],
  u: ["", "", " __   _  ", "[  | | | ", " | _/ |, ", " '.__.'_/", ""],
  y: ["", "", "  _   __ ", " [ \\ [  ]", "  \\ '/ / ", "[\\_:  /  ",
      " \\__.'   ",],
  _: ["", "", "", "", " _______", "|_______|", ""],
};

function generateAsciiArt(text) {
  const lines = Array(7).fill("");
  for (const char of text) for (let i = 0; i < 7; i++)
    lines[i] += asciiArtMap[char][i];
  return lines.join("\n");
}

generateAsciiArt(teamInfo.teamName);
for (const member of teamInfo.members) generateAsciiArt(member);