6/14 競技プログラムに挑戦してケチョンケチョンにされた

日曜の朝、急に「なんかかっこいいから競技プログラミングやってみようかな…」と思ったので挑戦してみた。競技プログラミングというのはプログラミングのうまさを競うやつで、なんか数学オリンピックみたいな感じだけど、Webサービスがあって、誰でも挑戦できるらしい。ちなみに俺の数学オリンピックについての思い出は、中学1年生の頃に校内で希望者が全員受けられる数学オリンピックの予選の予選みたいなのにノコノコ顔を出して、周囲の数学を得意とする同級生に囲まれて1時間ぐらい紙とにらめっこして最初の1問だけ解けたので参加賞のエンピツか何かをもらって逆に情けない気持ちになって帰ったことを覚えている。思えば数学に対する苦手意識はそのあたりから確実になってきたのかもしれない。

人と時間を測られたりスコアを競うような要素でモチベーションが上がる人と上がらない人がおり、義務教育は基本的には前者の人を対象とした動機付けを行っている。俺はどうやら後者の人だ。対戦系のゲームなんかも大体勝てないので、YouTubeで強い人の動画を見て動きを学ぼうとするも、動画見た段階で「ふ〜ん」と思ってやめてしまう。数学のテストなんかも時間制限なしで「ま、2,3日寝かしてみますわ。ちょっと自分なりに考えをまとめてきますんでね」というようなことが出来れば苦手にならずにいられたのかもしれないが学校というのはそういう場所ではない。式を暗記して、限られた時間で間違えずに問題を解くことを求められる場なのだ。自分がプログラミングを(一応)含む仕事についているのは学校でプログラミングを習わなかったからというのが大きいだろう。もし習ってたら確実に嫌いになっていた自信がある。なのになんで今さら競技プログラミングをやってみようと思ったかというと、そういう苦手意識で新しいことに手を出さないでいるとどんどん老いていく気がしてきたのと、昨日の夜に見てた記事に「天才プログラマ」の人が出てきて「天才プログラマ…かっこいい…」と思ったからだ。先日29歳になりました。

よくわからないけどとりあえず日本で最大手のAtCoderというサービスに登録してみる。AtCoderは基本C++で書くらしい。C++なんか一回も書いたことないけどまぁいけるやろとC++で解説されているチュートリアルを進めてみる。ブラウザのフォームに指定のめちゃめちゃ初歩的なコードを書いて、「提出」というボタンを押してしばらく待つと「正解です」みたいな表示が出てくる。なんかうれしい。練習問題みたいなやつもちょっと頑張って考えたら解けるぞ。ちょうど夜にBeginner Contestという初心者〜中級者向けの大会があるみたいなので参加してみようかな。

時間は夜の21時、ご飯も早めに作って食べた。参加ボタンを押して問題を開いたところで、数学のテストを受けてる時のあのイヤ〜な感覚がありありと蘇った。問題は6つあって、徐々に難易度が上がって行く。1時間後、俺は3問目とか4問目で悪戦苦闘している。制限時間は刻一刻と近づいていく。この一人だけ置いていかれて時間だけが過ぎていく焦り、焦ることでさらに自分が何を書いているのかわからなくなるこの感じ! 焦りすぎて業務では決して書けない自分史に残るレベルの汚いコードを提出した。(ちゃんと通ったからいいのだ)
普段の仕事のプログラミングで数学っぽいことをほとんどしてなかったので「言うてもそんな数学数学してないでしょ」と思っていたが、競技プログラミングは7割ぐらいは数学だった。数学的アプローチで問題を計算可能なサイズに変換して、それをコードに落とし込んでプログラムに計算させるというのが基本の流れだ。数学的アプローチのところがグダグダでもコンピュータで愚直に総当たりさせれば解けないこともないのだが、後半ではそんな甘い手が通用しないように計算の制限時間も設けられていて、実行に2秒とかかかったら得点がもらえないのだ。結局100分粘って前半しか解けなくて順位は1万人中の6500位ぐらいだった。ちなみに1位の人は25分ぐらいで全部終わっている。すごい。
最近ジャンプ漫画を読んでいるせいでやってみる前は「実は日頃の業務がすごいトレーニングになっていて、意外と良い線行ける可能性もあるんじゃないか…?」という思いが2%ぐらいあったのだが、そういうことは一切ないということがわかって逆にスッキリした。

おもしろい発見もいろいろあった。問題文に望ましい入力と出力の例がいくつか付いてくるのが良い。問題文と別に「つまりこういう入力があったらこういう出力を返すようにしてね」という文章がついてくるのだ。俺の場合は「そもそも問題文が抽象的すぎて何を聞かれているのかわからない」ということがよくある。数学が得意な人だと抽象的な概念を抽象的なままに操作することができるが、俺のような人間は一旦いくつかの具体的なもので考えてそれを抽象的な概念に置き換えるということをするまで理解することができない。いつでもそうやって生きてきた。今回もわけがわからなくなったら入出力のペアを見てパターンを掴むと「あー、そういうことね」とわかるタイミングがあった。
それから、数学のテストと違って競技プログラミングの場合は自分のコードを手元で動かして何度でも試してから提出することができる。提出したコードが間違ってた場合はちょっとペナルティもあるが、それでも提出し直すことができる。間違ってもいいからとりあえずやってみる、ということができるのは自分的には心強かった。(だからって解けないものは解けないんだけど)

終わった後でYouTubeのライブ配信で運営の人がホワイトボードで解説したりしてて、なんか予備校っぽい。何を言っているのかは半分ぐらいしかわからないものの、コメントで「ここ難しかった〜」とかの感想が飛び交っているのも謎の一体感があって楽しい。自分が書いた愚直なコードだと計算に時間が掛かりすぎてダメだったのが、エラトステネスの篩という古代ギリシャ人が考えたアルゴリズムを応用すると計算量がグッと下がって通るようになるのを見て、古代ギリシャ人すげ〜と思った。計算量のO(N*A)だったのがO(logN)になって…みたいなのはよくわかってないので聞き流す。というかlogが何だったのかあんまり思い出せない。とにかく計算量が下がるとかっこいいのだ。

ということで、まぁこういうのが向いてるか向いてないかというと向いてないし、「レーティング何点取れるように頑張るぞ!」みたいな努力の仕方は自分がやるとすぐ嫌になってやめてしまうのでやらないが、普通に勉強になるところも多いのでチマチマやってみようかなという気になりつつある。果たしてやるのだろうか…

あなたのコーヒー1杯ぶんのお金が、私のコーヒー1杯ぶんのお金になります