バグった原因集
みなさん、競技プログラミングやっていますか?こんにちは、ライターのもつ鍋です(言いたいだけ)。
競技プログラミングをやっていると、本質はわかってるのに、バグって無限に時間とかしたり、解けなかったりでガン萎えすることは数を知らないと思います。
と言うわけで、様々なバグの原因をまとめて、実際に詰まったときに、自分が参考にできるような記事を作ろうと思ったわけです。
この記事はバグったらその都度更新していくので、初期段階では情報量は無です、気にしないでください。あとみなさんからの色んなバグの原因、募集いたします。
⚠️そもそも解法はあっていますか?
どうしてもWAが取れないとかいうときに、バグを気にするのはわかります。ですが、そもそも解法が間違っていれば実装が正しくても当然通りません。バグを疑う前にまず方針が正しいかを確認しましょう。
バグ原因一覧
index関連
添字は全人類がバグらせます。丁寧丁寧丁寧に考えれば直るはずなので、頑張りましょう。
- iとjを間違える(アホみたいですが本当の話です)
- +1,-1ずれてる(しっかり立式するなどして、紙で確かめましょう)
- 0-indexと1-index(これは原則どっちかに統一した方がいいです)
- 配列外参照(これ気にするだけで本質が見えたりもします)
- 植木算(むずかしい)
- 2つ以上の管理してるindexをごっちゃにする(頂点と辺とか)
- メモリの確保し忘れ(1-indexにした時に、メモリ多く取らずに配列外参照したりします)
その他
index以外特別に分けるほどのものはなくないですか?増えてきたら項目が増えるかもしれません。
- オーバーフロー(大きくなりそうと思ったらしっかり検算を)
- YESとYes(やめてくれ…)
- 初期化まわり(とりあえず初期化はしましょう)
- 無駄にでかい配列(使い回しましょう)
- 同じ値を入れた複数のものをごっちゃにしないように(pairでよくやる)
- 浮動小数点数の比較(==での比較はよくないです)
- ライブラリが壊れてる(如何しようも無い)
- &&と||を間違える(適当に考えると引っかかりがち)
- return, break, continueなどのタイミングをずらす(CLionで書けば起こりません)
- 処理順のミス(ans += a[pos]とpos++が逆など)
- デバッグ出力を消し忘れる(異常時のみデバッグ出力すると、バグを取った後、サンプル実行しても気づかないことがある)
- 単調性は本当にありますか?(どっちでもいいときはとりあえずないと思っとく方が吉)
- 0は足しても0(それはそう)
- 一般にはa/b*b!=a(前に書いた式を簡略化しようとしてバグらせないこと)
- 入力順を間違えていませんか(カス)
- 思ってるのと違う関数が呼び出されてる(既存っぽい名前の関数使ってるとワンチャン)
- ライブラリがバグってませんか(終わりです)
- 答えの上界下界の勘違い(minを求める問題で初期値をあり得る最大にするときなど)
バグの解消術
バグったときはどのようにして解消すれば良いでしょうか。
まずはコードを読み直して、それで直ぐ気付ければ一番です。
それで無理なら、何らかのテストケースについて、想定通りの挙動をしているかをチェックします。この際デバッガなどを使うと楽だったりしますが、途中で気になる変数を出力するだけでも大体はわかります。
サンプルテストケースだと想定通りの挙動をしている場合には、愚直解のコードを別に書いて、答えが一致しないケースを探して、そのケースを用いて上のことをするのも良いです。
それでも無理なら、諦めて書き直しましょう。変なバグで一生を費やすよりは、半生を費やしてでも書き直した方が、実りのある人生になると思いませんか?大体直りますし、それでも直らないなら、大体解法とかが間違っています。
そもそもバグらないための策
バグを取るのは正直非常に困難です。最初からバグ書かないのが最も素晴らしいことです。その方法については、某ぽんと毎週のように話しているのですが、明確な回答は得られないままでいます。
しかし、自分なりの実装の流れを決めて(明示的でなくても良いので)、それに従って毎回実装すれば、バグはかなり減ると思います。事実として、私はそのおかげで最近かなりバグが減っています。
また何らかのIDEや高性能なエディタでコーディングすると、形式的なくだらないバグは直ぐに警告してくれるため、だいぶありがたいです。私は某いこの影響でCLionを使っているのですが、とても便利です。特に学生は無料なので、おすすめです。
もし「私、バグしないので」みたいな人がいたら、どういうことを意識しながらコーディングしているのか、ぜひ教えてください。泣いて喜びます。
それでは一旦ここで筆を置きたいと思います。意見をいただいたり、自分で新たなバグを発見したりするなどしたときに、また加筆していきたいと思います。それでは!