海外の競プロコンテスト Advent of Codeが楽しかった

今年は同僚の方に誘われてオンラインの競プロイベント [Advent of Code](https://adventofcode.com/) に参加しました！
とても楽しかったので、本記事で紹介したいと思います。

## 概要
Advent of Code(以下、AoC)は、Eric Wastl ([@ericwastl](https://twitter.com/ericwastl)) さんが個人で開催しているプログラミングコンテストです。
2015年から毎年12月に開催されており、今年は15万人を超える競技者が参加しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127392/456c2d55-cb8c-ea35-b2ff-9c9ab7f9b966.png)


このコンテストの特徴として、下記が挙げられます:

1. 12月1日から25日まで毎日1つ問題がオンラインで出題される
    * 問題1問ごとに2つのパートがあり、それぞれ1つずつ星[^1]を貰える
        * 星を合計2x25=50個集めるのが参加者のゴール
2. 1パートごとに1つのサンプルケースと1つのテストケースが与えられる
    * 解答時は、そのテストケースに対する答えをテキストで送信する
    * 単一のケースで答えが得られれば良いので、プログラミング言語は任意のものを利用可能
3. 問題の難易度は比較的易しめ
    * AtCoderなら茶～緑くらいの感覚
    * アルゴリズムの知識を問う問題よりは、実装メインの問題が多い印象
        * アルゴリズムはB/DSF, 動的計画法くらいが使えれば基本的にOK
        * [簡単な構文解析器を実装する問題](https://adventofcode.com/2020/day/18)もあった
4. 早く正解した人にスコアが与えられる
    * `n` 位の人は `max(101-n, 0)` 点がもらえる
        * 例えば1位の人は100点、50位の人は51点、1000位のひとは0点など
    * 星ごとにスコアが与えられ、スコアの合計でランキングが集計される
    * 誤答のペナルティもあり、誤答の送信後1分間は回答を送信できなくなる
5. ランキングはグローバルランキングとプライベートランキングの2種類ある
    * グローバルランキングは競技者全員がデフォルトで参加しているもの
        * スコアは星ごとに上位100人しか与えられないので、大抵の人は全期間通算0点で終わる[^2]
        * 正直ここで競うのは修羅なので、プライベートランキングへの参加を推奨
    * プライベートランキングは各プレイヤーが自由に作成・参加できるランキング
        * こちらのスコアは参加しているプレイヤーグループごとに集計される
        * モチベーション維持のため、同僚や友人とで同じプライベートランキングに参加することを推奨

## 楽しみ方
AoCがどのようなものか伝わりましたか？
この章では、私が実際に参加して楽しいと思ったポイントをまとめます。

#### 問題が2部構成であることの面白さ

AoCの問題はすべて、1問が2パートに分かれています。
例えば、パート1では2次元空間を考えていたのが、パート2で3次元に拡張される、などです。

パート1を解くとパート2の問題を読めるようになるのですが、この時問題が思いも寄らない方向に変わることがあります。

AoCでは基本的に早解きをしたいのでできるだけ、パート1の実装を使いまわしたいのですが、パート1の実装がうまくないと、パート2ですべて書き直しを余儀なくされたりします。
このため、パート1の時点で2の展開を予測して再利用性を考慮しつつ、予測が外れた場合にそれほど時間ロスにならない程度の単純さでうまく実装する必要があります。
このバランス感が個人的には結構楽しかったです。


#### Redditのコミュニティ [`r/adventofcode`](https://www.reddit.com/r/adventofcode/) は要チェック

AoCの競技者の多くは、このSubredditを交流場所にしています。
ここでは、AoC開催中の期間に毎日各々の解答コードが共有されたり、問題に関する議論が行われたりしています。

また、解法の可視化に力を入れる方も多数いて、 自分で解いた後に[`Visualization` フレア](https://www.reddit.com/r/adventofcode/search?q=flair_name%3A%22Visualization%22&restrict_sr=1)で閲覧すると2度楽しめるでしょう。

#### コミカルな設定の問題たち
問題は基本的にサンタクロースがクリスマスに向けて準備するというテーマで作られています。

AtCoderでもよくあることですが、問題の設定がカオスで、情景を想像するだけでも楽しいです
例えば[2020年の7日目](https://adventofcode.com/2020/day/7)は、カバンの中にいくつものカバンが入っている再帰的カバンの問題で、それを模した[ネタ画像が投稿されて](https://www.reddit.com/r/adventofcode/comments/k8ccpz/shiny_gold/)盛り上がっていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127392/16a9b2b0-b9eb-ee14-cc62-2aa743131534.png)


## 参加してよかったこと
以上のような楽しさがあり、私も無事25日間完走することができました。
それでは、完走してみて得られたことをいくつかまとめます。

#### 簡潔なコーディング方法を学べる

AoCでは早解きが重要なので、コードも短く簡潔に書けることが望ましいです。
これは特定のアルゴリズム等に依らない汎用的なスキルなので、AoCの最中に成長していけます。

例えば、配列中各要素の積を取りたい時、下記のように簡潔化できますね。

```ruby:書き方の例.rb
arr = [1, 1, 4, 5, 1, 4, 1, 9, 1, 9]

# 愚直な書き方例
mul = 1
arr.each do |a|
    mul *= a
end

# 簡潔な書き方例
mul = arr.inject(&:*)
```


私は一度問題を解いたあと、Redditに投稿される他の人のコードを読んでベターな書き方を探していました。
物によっては、その日得た知識を翌日すぐに活かせることもあったので、成長実感も得られやすかったです。


#### 毎日1日1回""考える""時間が強制的に与えられる

働いていると数学的・計算機科学的な思考をする機会は少なくなってくる場合もあるかと思います。
AoCでは問題が毎日1問だけ提供され、かつ難易度もほどよいものです。
コツコツした積み重ねが苦手な方も多い(私も)と思いますが、AoCでは自然と1日1時間だけという取り組み方が実現できます。

またランキングは、順位維持したいという欲求や他の人もしっかり解いているという焦りから、モチベーションを向上させてくれます。

このため、思考する・コードを書くことが容易に習慣化されます。

#### 同僚や友人との話のネタになる

毎日1問皆が同じ問題を解くことになるので、参加者同士では話のネタにしやすいです。
そういう意味ではドラマやアニメにも近い娯楽ですね！

## 終わりに
AoCというイベントの紹介をしてみました。
興味を持たれた方は、これまでの問題を確認して雰囲気を掴んではいかがでしょうか？

問題はいつでも解くことができ、2020年の問題は[こちらから](https://adventofcode.com/2020)アクセスできます。
また、昨年以前の問題は[こちらから](https://adventofcode.com/2020/events)も参照可能です。

次回の開催は1年後(2021/12)なので、ぜひ参加してみてください！


[^1]: 星は勲章みたいなものなので、集めても特に意味はない
[^2]: この仕様を変える提案は何度もなされているが、[サーバー負荷の問題ということで今の所変更予定はないらしい](https://www.reddit.com/r/adventofcode/comments/kkdb53/is_it_time_to_rethink_scoring/gh3hngf?utm_source=share&utm_medium=web2x&context=3)