2020-01-17競技プログラミングPython競技プログラミングをはじめた。はじめたと言っても、はじめてではないのだけどね。真面目にコンテスト参加をするようになったというだけである。これまでも何度かやってみてはいた。今回はなぜ続かなかったのかと、何がきっかけでやり始めるようになったかを書いておこうと思う。プログラミングの学習が目的そもそも私の場合、プログラミングコンテストへ参加するその最大の理由は、自分のスキルアップのためである。スキルアップというか、もっと具体的に言うと、たとえばKotlinの練習だったりするわけである。いうより当初はKotlinスキルアップの題材として、プログラミングコンテストを利用していた。この観点から言うとAtCoderは全く使えないので長続きしなかった。理由としては、AtCoder上のKotlinはバージョンが低すぎるからである。競技プログラミングにおいて、言語のバージョンはそこまで重要ではないだろう。言語バージョンが上がることによって増える便利な構文などに頼らず実装するのが競技プログラミングだろう。私の目的からすると、手元で使える書き方が使えずわざわざ古いバージョンでコードを書かないといけないのは本末転倒である。プログラミングはその殆どが、標準入力から入力を受け取り、標準出力に回答を出力する形式であろう。これが私にとっては障壁となっていた。その理由は、書いたコードをテストしづらいからだ。この観点から言うと、LeetCodeは指定されたメソッドを実装する方式だったので、ユニットテストで動作確認がやりやすく問題に挑戦しやすかった。LeetCodeも結局長続きしなかったわけだが。そのわけは、自分の書いたコードの効率の良さとかがさっぱり分からないからだ。コードを提出しても、LeetCodeではすべての提出されたプログラムのうち、あなたのプログラムはこれくらいの処理速度ですよというのが返ってくるだけである。その処理速度も、まったく同じコードなのに処理時間にブレ幅があり、指標として役に立たない。長続きしなかった最大の理由は言語の壁であったが。問題文を理解できずにそもそも土俵にすら立てないこともしばしばである。英語の勉強になるかなぁと思って少しずつやってはいたが、時間がないときに問題文の理解に1時間とか書けてられないという話である。いうことかなと思って実装しても、テストケースに通らずということも心をくじくには十分であった。それらの障壁が取り除かれたわけだAtCoderを再開するようになったのは、前述の2つの障壁が取り除かれたからである。1つ目は私の意識改革である。Kotlinにこだわるのをやめただけの話だけどね。現在はPythonを使って参加している。Pythonを使っている理由は、2つ目の障壁に関わる。2つ目の障壁は、Pythonで標準入力・出力をモックしてユニットテストを回せるようになったからである。いうよりPythonでこれができるようになったので、AtCoderに取り組みはじめたのである。Pythonを選んだ理由はそれともう1つ、標準入力からの読み込みが比較的ラクに書けたからである。標準入力からの読み取りが、競技プログラミングをやる上で障壁になってる気がするのは私だけだろうか。普段標準入力からデータを受け取るようなコードを書かないから、競技プログラミングのためだけにその部分で頭を使うのは嫌だったのだ。その点Pythonはinput()とすれば標準入力から受け取れるから楽である1。私気になります話は逸れるが、競技プログラミングに参加している人は、コードを実装したあとの動作確認をどうしているのだろうか。競技プログラミングはじめました的な記事はよく見かけるのだが、こういった話まで書いている人はあまり見かけない気がする。競技プログラミングでは問題文とともにサンプルデータとそれに対する出力例が提示される。これを使って動作確認をするはずである。私はPythonでユニットテスト環境を整えるまではコードを実行し、標準入力からサンプルデータをコピペして出力をチェックするというめちゃくちゃ面倒くさい方法をとっていた。これがめんどくさすぎて競技プログラミングが長続きしなかったと言っていい。類まれなる実装力を持っていて、バグなく実装できるとかいう超人なら別にこんなことはどうでもよいのだろう。私はそこまで実装力に自信があるわけではない。ときにはステップ実行して実装のどこがまずいのか確認しなければコードを完成させることができないこともある。そのステップ実行をやるたびに、標準入力へ入力値をペーストするのはすごい面倒くさい。ユニットテストができるようになってから、ようやく出発点に立てたと言ってもいい。このあたりはみんなどうやっているのだろうか。PythonでユニットテストPythonでユニットテストStackoverflowにあったコードを使わせてもらった。Templateを使ってさらにボイラープレート部分を減らしている3。実装したコードをユニットテストで回せるので、随分とAtCoderの問題をやりやすくなった。AtCoder以外でも恩恵がこれまた手を出したのは2年以上前だったりするのだが、AOJを使ってアルゴリズムの勉強もはじめた。こちらもPythonで実装している。標準入力・出力を使ったコードをユニットテストで回せるようになったのが大いに役立っている。問題を解くだけでは進歩がないと思ったので、アルゴリズムとデータ構造を買ってちゃんと学習することにした。こちらは少しずつ進めているところ。どの程度身についているかはよくわからないのだけども。AtCoderをやっていて、Dくらいまではなんとかできても、その先となるととんと歯が立たない。いった本を利用して学習しないとどうしようもないなと思ったのである。少なくとも三日坊主だけはクリアしている。一日一問くらいの進み具合ではあるが、少しずつ進めていっている。代わりにAndroidアプリ作成まで手が回っていないけれど。まとめ本エントリの肝は、Pythonで標準入力・出力を使ったプログラムをユニットテストできるようにしたら、競技プログラミングへの参加ハードルがぐっと下がったという話である。PythonでできたからPythonでやってるだけなんだが、他の言語でも標準入力・出力を使ったテストの書き方がわかればそっちへ移行というのもありかなと思う。Kotlinに関しては、AtCoder側のバージョンが上がらないと選択肢に上がらないが。他の言語でのテスト方法にも挑戦しようかとも思ったのだが、とりあえずPythonでできたし、Pythonでやってるとこれはこれで楽しくなってきてしまった。いうわけで、他の言語での方法を調べるよりも、Python使ってどんどん問題を解いていく方を優先している。他の言語で自分はこういうふうにしてユニットテスト回してやってるという知見があれば教えてほしいなというのが、今回のエントリを書いた私の下心である。いえinput()がくそ遅いので、これのせいで処理時間内に実行が終わらないこともあったりするので注意が必要だが。課金してるから使っているだけである。別にコミュニティ版PyCharmを使えばいいし、何なら他のエディタでもいい。↩main関数を定義して、スクリプトとして実行されたらそのmain関数呼び出すようにするとか、ユニットテストの定形部分などをテンプレート使って作成するようにしている。なんとかできんのかという部分もあるのだが、そこを突き詰めるより問題解いていく方が大事だと思って、ある程度の状態で満足することにしている。記事の内容に修正リクエストを送るAmazonのほしいものリストAmazonのほしいものリストを公開しています。仕事で欲しいもの、単なる趣味としてほしいもの、リフレッシュのために欲しいものなどを登録しています。寄贈いただけると泣いて喜びます。大したお礼はできませんが、よりよい情報発信へのモチベーションに繋がりますので、ご検討いただければ幸いです。