AtCoderで黄色になるまでにやったこと

AtCoderを始めて2年5か月くらいで黄色になった。

AtCoderを始めるまで

プログラミング歴はとても長くC++が好き、数学も難しいことはわからんけど適当でいいならできるという感じで、相当にAtCoder向きな能力セットを持っていた。

AtCoderの存在はけっこう前から知っていて、一度はやりたいと思っていた。直近のABCを解いたうえで、2017/1/28のABC053に初参加。思いがけず問題の質が高く、継続してコンテストに参加することとなる。

モチベ

健康のために数学っぽいことをしたいと思いつつ何もしない期間が長かった。その意味でAtCoderは渡りに船だった。プログラミングは得意だから障害にならないし、数学パートもけっこういい加減でよくて今の(当時の)自分でも気楽にできる。最初のころは、提出の実行時間や使用メモリがずらずらと表示されているのを見るだけで楽しかった。そのうちレーティングを気にするようになり、悔しがったり落ち込んだり何も感じなかったりしていた。ただ、今の自分がこれだけ感情を動かされることをやっている、それはとてもいいことだと思った。家にいながら緊張したりウンコしたくなったりなるのすごいよね。半年くらい前に気づいたけど体温まで上がるようになってた。たまたま、面白そうな問題があれば解きたいと思い、順位表があれば勝ちたいと思う性格だったので、コンテスト中はそれなりに集中できたのだ(コンテストの時間は100分とか120分とかで、そのくらいなら)(あまり集中できない回もあった)。参加して普段と違う空気の中で考える価値が非常に高いと思っていた。

というわけで、基本的には自分の数学方面の力を維持する(または低下をゆっくりにする)ためにやっている。「レーティングは集中するためのエサに使ってるだけでどうでもいいんですよ」とか表面上は言う。

やったこと

勉強方法

コンテストに出て復習が基本。最初のころは、過去問(ATC001とか)をやって周辺知識をネットで検索する感じで典型知識を増やしていった。1年くらい経つとyukicoderのコンテストにも出るようになった。AtCoderの問題は難易度によらずめちゃくちゃ親切なので、yukicoderで普段と違う筋肉を鍛えたいという意図もあった。なんだかんだ面白い問題あるし、たまに知らないド典型が出る。

復習の具体的な中身は、コンテスト中に挑戦したけど解けなかった1問を解くこと(王道)と、解けた問題を納得行くコードで再提出(納得ポイントは、コードの見た目のきれいさと実行速度)。少し考えて進展がなければすぐ解説を見る(だらだらと考えちゃうこともあるけどあんまよくない)。最近特に心がけていたのは、やりたくないことはやらないということ。それで放置された問題もたくさんあるが、それでいい。苦しみながら進めるほど簡単な道のりではないはずだ(それっぽいことを言う)。

僕個人については、練習によっていまさら地頭が付くはずがないと思っている。しかし、そんな中でも難問を解けるようになるための方法は存在して、それが「簡単な問題を瞬殺できるようになること」。10分かかったことが1分で、1分かかったことが1秒で、1秒かかったことが0秒でできるようになれば、思考の質は変わる。難問を解くための練習は難しくても、簡単な問題を解くスピードを上げる練習ならいくらでも考えようがある(前述の「納得行くコードで再提出」がそれかな(あんま深く考えてなかったけど))。

とにかく、コンテストに参加するのが、練習としてはコスパが良すぎる。最近知ってびっくりしたんだけど、ABC132が終わった時点で参加回数(ratedコンテストのみ)が84回、これがAtCoder全体で40位タイなのだ。参加数上位には日本人しかいない。毎週普通に参加できてるのは思ったよりレアケースだった。

開発環境

普通にVisual Studio Community 2019。ソリューションの中にプロジェクトを2つ入れて、片方でC++を書き、もう片方のサンプルケースでテストする部分はC#で書いた。さらに、Firefox+userChrome.jsで現在表示しているタブのサンプルケースが自動でダウンロードされるようにしてある。これにより、実行ボタンを押すだけでサンプルを実行し全て通ればソースコードをコピーしてFirefoxをアクティブにし提出欄にフォーカスを当てるようになっている(あまり完成度は高くないけど自分で使うぶんにはいいかなくらい)。

サンプルの自動実行は非常に便利。そもそもコンテスト中の時間というのは集中して問題を考えることができる貴重なものであり、たとえ30秒でもサンプルのコピペに毎回使ってしまうのはもったいない。答えが複数ある問題の場合は、サンプルに対する出力が正しいか判定することはできないが、自分のプログラムの出力と出力例を並べて表示できるのでこれも便利。

Visual Studioコードスニペットで、たとえばfor[Tab][Enter]とするとfor文が書ける。これを競プロ向きにカスタマイズした。cin3で3つの入力を受け取るとか、sortでsort(v.begin(), v.end());が出てくるとか。自分は(あくまで競プロerとしてはだけど)タイピングがそれほど速くないので、重宝している。

MSVCとgccでは挙動が異なることがある。たとえば、int64_tの型が違うとか、includeが足りなくても動いてしまうとか。なので、カスタムビルドツールでMinGWgccを使っている。コンパイルオプションは-std=gnu++1y -Wconversion -W -Wall -O0。

ライブラリ

よく使うものだけを挙げる(ただのコピペ元もありますね、コードスニペットにするかの判断は気分)。

素数列挙、最大公約数、1000000007、組合せ、二分探索、UnionFind、グラフ(DFSとか)、ダイクストラ法、BIT(Binary Indexed Tree)、ソートできる構造体、cout << (b ? "Yes" : "No") << endl;、printf("%.8f\n", x);。

他にも、ライブラリにできそうなものは片っ端からしている。最近作ったのはModIntと行列累乗。使用頻度が低いものはいざというときに上手く使えないが、カプセル化の訓練としてはよい。ライブラリの作り方は力の差が出る部分だと思っている。中身をしっかり理解していれば柔軟に使えるし、一方で混乱しているときに無思考で使えることも重要。

コンテスト中の立ち回り

順位表を見るようになった。順位表を見てもそこから下がるだけなので見たくなかったが、少しずつ見るように頑張った。解けそうな問題を知るというのもあるけど、展開を知って油断せず取り組みたいというのが大きい。やはり状況を知っていたほうが楽しめる。

AGCとかでAは通したけどBとCのどちらをやるか迷うという状況のときは、楽しそうなほうを解くことにした。特にそういうことがないなら、交互にやる。「B無理、Cのほうが可能性ある」「いやCは不可能、Bのほうが」と自然に交互になる。時間はかかっても解ける問題を逃さないのが大きいし、時間を有効に使える(順位で不利になってもガツガツ考えたほうが楽しいし実際は順位が不利になる感覚もない)。最近は、最終的に解けない(そして落ち込む)ことはあっても、座ってるだけとか不完全燃焼ということが少なくなった。

考察では紙のノートと鉛筆を使うが、これに加えてソースにコメントで書きなぐるようにもなった。紙に文章を速く書くことができないので、それならPCで書いたほうがいい。編集も楽だし。そのまま提出すれば考察メモがわかりやすい場所に残るのもメリット。文章は、図やソースコードで表現しきれないことを簡単に表現できることがあり、思ったより便利だった。脳内メモリが少ないのでどんどんアイデアを出して、目から供給しながら考える。(もちろん、図で考えたり目を瞑って考えたりもする)(碁石と碁盤を使うことも最近あったな)

あと実装について。自分がC++を書くときはいつも実行速度を重視していた。競プロでは定数倍高速化に意味がないので、あまりこだわると不利になってしまう。ここはけっこう迷う部分だった。最近は、それなりに速度重視で書いて余裕がないときは速度を犠牲にわかりやすく書くという、わりと理想的(略してわりとり)な動きができている。自分のスタイルで書けば力を発揮しやすいし、いつも似たコードを書くことになるのでミスも出にくい。

どんな力が付いたか

自分は元々青程度の力があった。続けることでレーティングはじりじりと向上したが、これはAtCoderに慣れたことによるものだろう。開発環境とライブラリの整備も大きい。それ以外の伸びしろは、自分にはないと思っていたけど、最近ちょっと感じるのは、名前の付いていないたくさんの典型が身に付いてきて自然に応用できてるんじゃないかということ。まあ今黄色になったということは成功が続いているわけで、それによる勘違いかもしれないけど。勘違いだとしても、少なくともプログラミングや数学の力は維持できていると思うし、そう思えているのはまさに望み通りの展開で嬉しく思っている。

ぷよぷよ

さて、2018年3月にぷよぷよを始める(おいうリーグを見てほぼ未経験から始めた)。これにより精進量が減った。AtCoder ProblemsのHeatmapを見るとその時期を境にして明らかにサブミットが減っていた。ただ、毎週のコンテストには出ていたし、7月になってもレーティングへの影響は見られなかった。ここで、1か月以上ratedコンテストがないというかつてない事態が発生する。次のARCで最低パフォーマンスを更新し、レーティングは1994(Highest)から1937まで下がった。そこから半年程度レーティングが低迷する(といっても、それまでより50低い程度だけど)。実力が下がったというよりは、コンテストのやり方がわからなくなったというような心理的なものだったと思う。そもそもAtCoderは練習したところで半年程度で結果に出るような場所じゃないと思っているが、不調に陥ったとき練習量という支えがないと長く引きずりがちなのかなとは思う。

コンテスト前にぷよぷよをやると考察中にぷよぷよの盤面が浮かぶということで、AtCoderがある日の夕食後はやらないようにしてたりも。これも後から考えると行動を縛るデメリットのほうが大きそうだ。それだけぷよぷよに集中していて、それはいいことなんだから。近ごろは目を瞑ってぷよが浮かぶことがなくて寂しい。

2019年6月になり、この頃には状態がかなりよくなっていた。ぷよぷよと競プロをわりと自然に両立できている。元々素養があった競プロと、去年突然始めたぷよぷよ、以前は排他的な関係だったのが、なじんできたのだ。両方好きなのでとてもうれしい。

この項目を書いてたらようかんマッキーが始まった。ブログ書きたいのに勘弁してほしい。強くなりてえな。

なった

6月は、レーティングが1980以上の時間が長かった。つまり、運次第で黄色になれる状態だ。数週間前からこういう記事を書きたいと思っていたので、ほんとに運次第では行けると実感してたんだよ。確率は5割よりずっと低いイメージだったけど。んで、自分の実力が2050あるなら運が悪くてもいつか黄色になれるが、実際は1950程度だと思っているため、この1980以上を維持している好機を逃したくないと思っていた。コンテスト中、物音が気にならないほど集中するとかはできないんだけど、持てる力を集中させて臨んでいた。コンテスト後、明け方まで眠れないことも何回かあった(べつに終了後も興奮している自覚はなくて穏やかな心なのになんか眠れない)。

そしてABC132、全完でワンチャンHighest更新あるかもと思っていたら黄色になっていた。1950以上の状態だとレーティングが上がりにくく下がりやすいことを嫌というほど実感していたので、にわかには信じがたい。rated対象の中ではかなり上位だったのでなんかブーストかかってギリ橙パフォが出たんだね。橙パフォが出ればそりゃあ大幅に上がる。

実感がない。なんか全然嬉しさが湧いてこなくてびっくりした。そうだね、黄色は明日なるんじゃなくて今なるんだね。一生なれない可能性も高いと思ってたけどその時は来た。まあ今はうかれてこんな記事書いてるけど。

黄色になってよかったこと

今の自分は精神ダメージを負いやすく、嫌なことが起きたり懸案事項があったりすると何をやってもパフォーマンスが1段階落ちてしまう。すると、何かあったときそのせいで黄色になるチャンスを逃すんじゃないかとよけい気にしてしまうことがあった。その心配がなくなったことで、嫌なことがあってもあまり気にならなくなった気がしている。嫌は嫌だけど苦痛じゃないというか。お前レーティングを気にしすぎだろって感じだけど、まあ黄色になれる可能性がちょっとあるならどうにかしてその可能性をつかみたいと思うのはわかってもらえるかと。けっこうね、いろんなことをどうでもいいって思えるの大事。

まとめ

僕、将棋ウォーズで初段なんだけど、AtCoderでも初段になれて嬉しい。