自分のこと、それなりのエンジニアだと思ってたけど、緑コーダーになるのに1年かかった話
はじめに
2021年2月6日(ABC191) からAtcoderに参加し、2022年3月12日に緑色になりました
無事入緑しました!長かった・・・
— オ-℃ (@kazu_kun0716) 2022年3月12日
kazu_0716さんのAtCoder Beginner Contest 243での成績:2319位
パフォーマンス:1025相当
レーティング:785→812 (+27) :)
Highestを更新し、6 級になりました!#AtCoder #ABC243 https://t.co/5vNwurH14q
その後も、無事なんとか緑色で維持し続けています(2022年4月23日 rate 817)
巷では、数ヶ月で水色等になる人もいる中で、時間かけてるし、結構頑張っているけどなかなか結果が出ない人も多いのではないかと思います。 そういった人に対して「こういう人もいるんだ」とか「もう少し頑張って続けてみよう」とか思っていただければいいなと思って書きました。
進歩の速度は人それぞれで、かけられる時間も環境によってマチマチの中で、自分なりにやってきたことを共有し、1人でも多くの人に参考になることがあれば嬉しいです。
スペック
著者のスペックに関しては下記になります
エンジニア歴 約8年
プログラミング
- Python: 7年
- Java: 4年(業務歴では 1年強)
- Golang: 1年
- JavaScript: 2年 (TypeScriptの1年も含む)
家族構成 子供2人
- 妻との共働きで、家事育児もあるため、エンジニアリングの勉強時間は限られている
取り組んだキッカケ
Atcoderに取り組んだのは、数年前に外資系の会社でSoftware Engineerの面接を受けたことがキッカケになりました。 自分自身、様々な業務でエンジニアとして働いてきて、それなりに自分のスキルに自信を持っていましたが、全く何も通用せず散々たる結果になりました。
有名なOSS commiterでも試験が解けずに落ちてしまうことがあるようです。 自分の場合は、一応情報系のことを大学で勉強しましたが、例えば「木構造」がどういうものなのかは知っていても、0からフルスクラッチで書いたことはなかったですし もし必要があれば、組み込みや3rd partyのライブラリを使って解決してました。
また、アルゴリズムに関しても、「ダイクストラ法」を知っていて、机上の手計算しながら説明はできるが、実際コードに短時間で落とし込むのは難しいといった感じでした。 計算量や、メモリ効率に関しても、そこまでシビアな中で開発しなかったのでその辺りも結構なんとなくできてしまったのかな?とも思います。
コーディングテストに関しては賛否があるようですが、シリコンバレーを中心としたIT企業では現状実施されていますし、自分自身「データ構造やアルゴリズム全然わからん」ってことに気づけたので、ちゃんと勉強したいな!と思うようになりました。
Atcoder 緑色のレベル感
過去、Atcoder社 社長のchokudaiさんは下記のように述べています
緑色 (Cランク R800~1199 上位30%) 緑色になれれば、「競技プログラミングに熱心に取り組んでいる人」と考えて問題ないでしょう。 if、forはもちろん、それを組み合わせて2次元配列に対して操作をしたり、深さ優先探索や幅優先探索などのキューや再帰を使った実装も出来る。 簡単な動的計画法の問題や、数学的に工夫する問題など、計算量の工夫も出来始める。
が、近年の参加人数の増加により、全体の底上げが図られているような気がしており 下記でも述べられていますが、若干上振れしていると自分も思っています
個人的には、chokudaiさんのブログで言うところの緑と水色の中間くらいかな?と思ったりします
緑色になるまで
ratingの遷移は下記の通りですが、3つのステージに渡って、やったことを紹介できればと思います。
- 第一時成長期(約 3ヶ月)
- 伸び悩み期(約 8ヶ月)
- 再成長期(約 1ヶ月)
当初の計画
まず、上記の記事を見てどのように勉強していくかの計画を立てました。 正味、結構エンジニアやってきてるし、半年くらいで水色くらいにはなれるだろ!って思ってました(笑)
プログラミング言語としては、C++でいくか、Python3(pypy)のどちらを使うか迷いましたが、自分の使い慣れた言語がいいと思い、Python(pypy)でやることにしました。 C++と違い、速度面、競プロでよく使う標準ライブラリがない(ex. python では multisetがない) などの問題はありましたが、緑になる分にはそれほど大きな問題はないかなと、現時点では思っています。
第一時成長期(約 3ヶ月)
やったこととしては
毎週 Atcoder Begineer Contest(ABC) に参加する
- 下の子が0歳児の中、妻にはだいぶ迷惑をかけたが、なんとか時間を確保した
- お風呂入れる時間が押してしまって、参加が遅れたりしたこともあったり、旅行先のホテルで寝かしつけた後、参戦したりしたこともあった
- 下の子が0歳児の中、妻にはだいぶ迷惑をかけたが、なんとか時間を確保した
コンテスト以外の時間での、勉強時間の確保
- なるべく毎日1時間以上コードを書く(2時間程度が理想)
- 空き時間の確保や、他の趣味の時間を削る等で対応
参加したコンテストの解説記事を書く
- 結構時間とられるので、今はやめてしまってますが、近いうち再開しようと思っています。。。
- AtCoder Beginners Selection を全部解いた
- 上記が完了してから、下記で紹介されている 分野別 初中級者が解くべき過去問精選 100 問 を解き進めた
この辺りは、 レッドコーダーが教える、競プロ・AtCoder上達のガイドライン
で紹介されているものを踏襲した感じになります。
ただ、あまり勉強せずともABCのC問題くらいまでは解けることが多かった。が、D問題から先はさっぱりという感じでした。
ABC Likeなコンテストでミスをしてratingを下げたこともありましたが、順調にrating を上げていき茶色になることができました。 また、基本データ構造の計算量に関しては知らないと、正しく計算量の見積もりができないので、下記を頭に叩き込みました。
伸び悩み期(約 8ヶ月)
茶色になってからですが、rating が伸び悩みます。ABC で C問題までしか解けないというのもあり、パフォーマンス相当のrating になったというのが大きな原因かと思いました。 なので、方針としては下記の2つを進めていくことにしました。
- 早く、正確に現在解ける問題を解けるようになる
- AtCoder Problems で、C問題までを早く、正確に解くことを進めた
- 対象は、現行の形式になった、ABC126 よりも新しいものとした
- 3ヶ月程度で完了した(2021/8/23 commit)
- より難しい問題が解けるようになるように、アルゴリズム/データ構造を学び、解ける問題を増やす
- 分野別 初中級者が解くべき過去問精選 100 問 を解く
- が結局、最後まで解き切らなかったと思う。。。モチベーションが続かなかったので
- AtCoder Problems 、D問題を埋める、緑色以下のdiffを埋めるといったことを行なっていった
D問題以上特には、競技プログラミングでよく用いられるアルゴリズムやデータ構造が理解し、使いこなせる必要があるので、分野別 初中級者が解くべき過去問精選 100 問を解き進めるのですが、新しいアルゴリズムを勉強して理解して、例題を解くのは自分にとっては大変でした。
英単語や文法の暗記系と違って、アルゴリズムという取っ付きにくいものを理解して、使いこなせるようになるには、まとまって集中する時間を確保しないと難しく、隙間の30分やって、別の時間60分という形で進めると非常に効率が悪かったです。 子持ちで、フルタイムの仕事もあるので、平日/休日で決まった時間を確保することが難しく、特に育児は突然予期せぬことが起こるので、その都度対応する必要があったので、その度にストレスを感じてました。
また、「自分が解けなかった問題の復習」に関してもそうですが、解説読んでも理解できないし、考えているときに中断して、また再開して・・・という感じで、非常に苦しかったです。
停滞期に突入する
Atcoder ProblemでのD埋めも終盤に差し掛かり、必要なアルゴリズムも一通り勉強終わったけど、中々D問題がコンテスト中で解けないといったことが続きました。 正直、結構問題解いてるし、自分で解く分には解けることもあったので、なんでなのかなーと思ってましたが、そこまで深く考えてなかったです。
D埋めしてて、結構解けるようになってきたけど、4完遠いな・・・
— オ-℃ (@kazu_kun0716) 2021年10月2日
腐らず続けるぞ!
はてなブログに投稿しました #はてなブログ#Python #ABC221 #競技プログラミング #Atcoder
Atcoder-ABC221をpythonで解いてみた - EAFPhttps://t.co/aiRGbRSa0f
まーた、D問題解けんかった・・・コンテストじゃないのに解けるのにねw
— オ-℃ (@kazu_kun0716) 2021年10月9日
とは、いうものの諦めたらそこで試合終了なので、苦しいながらも続けるぞ!
はてなブログに投稿しました #はてなブログ
Atcoder-ABC222をpythonで解いてみた - EAFPhttps://t.co/fIAeJR9BGM
が、いよいよABCのD埋めも終わったところで、解いている問題量に対して、結果が伴ってきてない実感が強くなりました。 結論言うと、解いて終わりで復習してないってのが原因だと思うのですが、2度同じ問題解く気がしなかったので、競プロ典型 90 問を解くことにして、さらに演習を進めると言う選択をしました。 今思うと、勉強法を見直すべきだったかなーと思うので、今後取り組む人は、一度解いた問題も復習すると良いと思います。コンテスト後に解けなかった問題解いて、さらに1週間後解いてみるとかすると良いかなと思います。
そういえば、ABC126(6問体制になってから)のD埋め
— オ-℃ (@kazu_kun0716) 2021年11月3日
緑diff以下に限っていうと、あと1問で達成だなhttps://t.co/D1l9QyQKwz
結構時間かかったけど、ようやく終わる・・・
また、解けなかった時に、解説見てもわからない時に、Youtubeでの解説動画を見てましたが、これをみて分かった気になっていたと言うのもつまづきの原因かもしれません
スッゲー時間かかったけど解いたぞ!
— オ-℃ (@kazu_kun0716) 2021年11月20日
ありがとう!かつっぱ先生!
提出 #27407501 - トヨタシステムズプログラミングコンテスト2021(AtCoder Beginner Contest 228) https://t.co/87K2yt06x5
ガムシャラに問題を解き進める
競プロ典型 90 問を進めていきます。最初は★5以下の問題を解いていましたが、まずはD問題をコンテスト中に解けることが目標なので、★4以下にして、90問解きました。解いた問題に関しては、READMEにまとめてみたので、興味ある人はみていただけると良いかと思います。
また、DPが苦手だなーと思ったので、Educational DP Contest / DP まとめコンテストにも取り組みました。あまり難しい問題までやっても解けないので、J問題までやりました(「最適化問題」以外にも使えることがわかるという説明があったので。)。
非効率かもしれないですが、Dを埋めた後取り組んだのもあって、それなりにスムーズに解き進められて、かつ過去問の類題もあったので良い復習になったのかなと思います。
定期的にCでコケるが続く
ratingは長期的に見ると、少しづつ上がっているのですが、上がっては下がるを繰り返していました。これが、停滞期の原因であることに気づくのがとても遅かった気がします。
緑、茶色解いてきたけど
— オ-℃ (@kazu_kun0716) 2022年1月13日
実はC埋めをさらに進めて、穴無くすのが抜けてるのかな?
下記をみると顕著なのですが、定期的に -30
前後を食らっています。これは、C問題が解けなかったり、めちゃくちゃに時間かかったコンテストになります。
コンテスト中に解けなかった問題で、かつ灰色difficulty(rate: 400以下の人で50%の確率で解けると思われる問題)を見返してみると、基本的な数学/ 情報科学の基礎力があれば解けるような問題でした。
- AtCoder Beginner Contest 234 C - Happy New Year!
- AtCoder Beginner Contest 224 C - Triangle?
- サイシードプログラミングコンテスト2021(AtCoder Beginner Contest 219)C - Neo-lexicographic Ordering
- AtCoder Beginner Contest 206(Sponsored by Panasonic)C - Swappable
- AtCoder Beginner Contest 196 C - Doubled
なおかつ、コンテスト中に全く歯が立たない!と言うことではなく、サンプルは通ったけど、WAが取れずに終了してしまうという傾向があることがわかりました。 ミスの傾向としては、下記がある気がしています。
- 問題文の読み間違い/ 勘違いをしている(ex. 前提となっている条件を見落として、勝手に問題を複雑にしている)
- コーナーケースを想定できていない(ex. N=0の場合の場合分けなど)
- 単純な実装ミス
debug 力は一朝一夕では身につかないので、この辺りの記事も見ながら気をつける!ということを続けました。
また、Cコケは不可避で起こったら、復習して周辺知識深め、また次頑張ればいい!と言う風に割り切ることにしたことも良かった気がします。 あまり、rating に拘らず、楽しんでやる心を改めて思い出して取り組むようにしました。
ここまで、勉強したアルゴリズム/データ構造に関して触れていないですが、2 個の基本アルゴリズムをマスターする!で触れられてるもの以外、特に勉強していないです。強いてあげると、
- 強い人と話すとよく出てくる「セグメント木」というものを勉強した
- pypyはpythonに比べると遅いという問題に対して、pypyjitを利用
from pypyjit import set_param set_param("max_unroll_recursion=-1")
- sorted multisetという、pythonでC++のmultisetようなことをしてくれるものを利用している
復習で、ABC245 E解けたhttps://t.co/CjtsIuSNsm
— オ-℃ (@kazu_kun0716) 2022年4月1日
SortedMultisetに感謝https://t.co/vgYlOEEyu4
2次元の貪欲法だーと思って、解けるかなーと思って椅子を温めた50分だったなー
次は解けるようになろう
といったことを +a で勉強しました。
再成長期(約 1ヶ月)
停滞期ながらも、ひたすら精進を続けていたら急にD問題が解けることが続くようになりました。 原因はわかりませんが、今まで解いてきた問題が身になったということに尽きるのかなと思います。
また、停滞期であっても続けられたのは、前職のOB/OGのSlackで競プロやるメンバーのチャネルがあって、そこで結果を報告しあったり、教えてもらったりしたこと。 現在の会社でも、毎週競プロの勉強会を主催し続けてきたこと、その中で自分より遥か上の人たちの知識や、考え方を吸収したり、教えてもらえたこと。 が大きかったなーと思います。結構1人でやると、辛いし、なにやってんだろ?って思うことも多かったんですが、仲間がいることで乗り越えられたような気がします。
まとめ
1年以上の時間をかけて、合計600問以上の問題(取り組んだ問題は、下記にまとめています)を解くことで、緑色コーダになれました。進歩の速度は人それぞれで、他の人のブログをみると3ヶ月とかでなっている人も多い中だと、自分は相当遅い方かな?と思います。
ただ、アルゴリズム/ データ構造の自力だったり、かけられる時間だったりで、この期間は大きく変わるかな?と思うので、他人と比べず、自分のペースで精進続けられればいいかなと思います。 もし「全然茶色から抜けられない」とかって人がいれば焦らずコツコツ続けるのがいいかなと思います。モチベーション管理が難しければ、友達や職場で勉強会立ち上げて取り組んでみるのは1つ選択肢としてあるかもしれないです。
競プロって、データ構造/ アルゴリズム仕事にしたりしない場合、使わないし意味ないんじゃないか?みたいな議論もあります。が、個人的には、下記の点において大きく能力が向上したと感じるので、1エンジニアとしてやってよかった、今後の実務に生きる!と感じています。
- 計算量/ メモリ効率も見積能力の大幅な向上
- 問題を考察し、実装に落とす速度の大幅な向上
- 基本ライブラリや言語仕様に詳しくなった
- 実装速度の大幅な向上
- コーナーケースの想定考察力向上(テスト書くときとかに役立ちそう)
- コードを実行しない中でのdebug能力(静的解析)の大幅な向上
今後ですが、水色になるにあたっては、問題の考察力がたらないので、しっかり考察して筋の良い実装方針立てる力を磨いていければと思います。 水色いつなれるかわかりませんが、色変したらまた記事を書こうと思います。
長文にもかかわらず、最後まで読んでくださりありがとうございました。