プログラミングの勉強を始めた
コンピュータエンジニアとしての幅を広げるためにプログラミングを勉強することにした。コンピュータサイエンスは修士まで取ったし新卒最初のキャリアがサポートエンジニアという過酷な走り出しだったので、そこそこシステムを俯瞰した考え方はできているのかもしれないが、コードが書けないので受けられる案件がかなりニッチになってしまう。それで、猫も杓子もやっているという競技プログラミングがプログラマにとっての知の高速道路(ただしその先が大渋滞)になっているらしいので私も渋滞するまでやってみようと思った。
私と競技プログラミングについて前置きしておく。大学生のころ、ICPC、AOJなどはあったけれど問題が堅くてあまり積極的に続ける気持ちにならなかった。複雑なアルゴリズムはほとんど定着しておらず、低レイヤー族なのでデータ構造だけは結構覚えている程度。唯一出ていた教材(蟻本)も最初からいきなり難しくてほとんど読まずにほこりをかぶっていた。そして、当時は ICPC に行ける天井人でなければ自分がどれくらいできるのかよくわからなかったから、参入障壁が高かったのだ(当然だが、そんな私たちでも勉強できる AOJ をメンテして指導してくださっていた渡部先生には感謝しかない)。コードを書かない今となってはほとんど、"はじめてのプログラミング"くらいの感じになってしまったのである。
当時と比べて今は教本も豊富で、AtCoder のおかげで日本の常識的な時間帯にコンテストに参加できる上に、実力も細かく刻まれていてモチベーションも保ちやすくなっていた。なにより、AtCoder の問題はなぜだか緩くて熱中できる。
勉強方法の調査
AtCoder は参加者全体のコンテスト結果の相対的な実力でレーティングがされており、レーティング帯で色分けがある。
400ごとに色がついていて、赤・橙・黄・青・水・緑・茶・灰・黒、という順番になってます
とりあえず水色くらいまで行けばいろいろと安心らしい。それでも平均的に半年以上はかかるようだ。勉強時間的に、TOEIC 900 程度になるのと同じくらいの険しさかなぁと思う。
水色なるとみんな体験談を書きたくなるらしく、ネットには先人の記録が無数にある。
- 毎週、AtCoder Beginners Contest(ABC) に参加するといいらしい
- ABCDE と難易度順で問題があるのでD, E くらいまで粘れるようになると 緑、水色に差し掛かるらしい
- 過去問を埋めるにしても A B C D と順にやっていき最初に解けなかった難易度を理解するというのを繰り返すといいらしい
なるほど、なるほど。
C++ 全く知らないレベルだったので先にこれをざっと読んだ。分量が多いのに対して例題は簡単すぎるので深追いはしなくてよい。
それから、この初級問題集をすべてやった。これで ABC の C までの感覚がわかる。
私はだいたいABCの過去問の C~D で完全に分からない問題が出てくる。これがアルゴリズムの理解の壁なので、教本で主要なものを拾うと良さそうだ。
大人なので主要な本をすべて買ってしまった。
ざっくり読んだところ、新しいだけあって AtCoder に特化して最短で勉強できそうなのが3冊目だった。基本はそれで進めて、わからなくなったらアルゴリズムイントロダクションと並んでこれらを横断的にやるのが効率が良さそう。
環境構築
ここが実は本題。
AtCoder を解くに当たって非常に有用なユーティリティがあったので利用させてもらう。CLI で問題のURLの確認、ディレクトリとファイルの整理、テンプレート使用、テスト、送信などができる。
インストール
$ npm install -g atcoder-cli $ pip3 install online-judge-tools
C++ 用の環境設定
$ mkdir -p `acc config-dir`/cpp $ confd=$_ $ cat > $confd/template.json <<EOF { "task":{ "program": ["main.cpp"], "submit": "main.cpp" } } EOF $ cat > $confd/main.cpp <<EOF #include<bits/stdc++.h> using namespace std; int main() { } EOF $ acc config default-template cpp $ mkdir -p ~/.local/include/bits $ cat > $_/stdc++.h << EOF #include <iostream> // cout, endl, cin #include <string> // string, to_string, stoi #include <vector> // vector #include <algorithm> // min, max, swap, sort, reverse, lower_bound, upper_bound #include <utility> // pair, make_pair #include <tuple> // tuple, make_tuple #include <cstdint> // int64_t, int*_t #include <cstdio> // printf #include <map> // map #include <queue> // queue, priority_queue #include <set> // set #include <stack> // stack #include <deque> // deque #include <unordered_map> // unordered_map #include <unordered_set> // unordered_set #include <bitset> // bitset #include <cctype> // isupper, islower, isdigit, toupper, tolower EOF $ echo 'export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:~/.local/include/' >> ~/.bashrc
ログイン
$ acc login $ oj login https://atcoder.jp
新しいコンテストへの参加
$ acc new <contest name (e.g. abs)>
ローカルでのテストをパスしたら提出
# タスクのディレクトリで $ g++ main.cpp && oj t -d tests && acc s
次の問題の準備
# コンテストのディレクトリで $ acc add
初めてのコンテスト
というわけで先ほど初めてのコンテストに参加してみた。目標の3問(A, B, C 問題)完了が達成できたのでよかった。ここまではアルゴリズム自体の勉強をしなくても落ち着いて考えれば解ける。
少し残念だったのが D 問題。これは動的計画法かメモ化再帰という技が使えれば解ける。私は直前までそれらを勉強していたのに、時間が足りなくなってしまったのと、アウトプットできるレベルまで定着してなかったので解けなかった。理解することと使えることは違うのだ。これは英語の勉強と似ている。
解説がすぐ上がってくるのは良い。(この解説の雰囲気、懐かしい...)
勉強は github で管理することにした。
コンテストとか勉強した分野ごとにコミットすると自分でも振り返りやすい。
無色からついに灰色(1回参加)になった...!
一年以内には水色になれるよう頑張ろうと思う。