feature image

2020年3月24日 | ブログ記事

競プロデバッグ術【新歓ブログリレー2020 16日目】

はじめに

こちらは新歓ブログリレー2020 16日目の記事です。

こんにちはebiです。自分は競技プログラミングをしたりJavaScriptを書いたりしています。

この記事では競技プログラミングをするときのデバッグについて書きたいと思います。競技プログラミングについてはこの記事を読んでみてください。

デバッグってなに?

Wikipediaによると

デバッグ(debug)とは、コンピュータプログラム電気機器中のバグ欠陥を発見および修正し、動作を仕様通りのものとするための作業である。

とあります。要するに書いたコードのバグ取り作業のことです。

プログラムを書いていると自分の意図とは違う動作をしてしまうことがあるためそれを直して意図どおりの動作をするようにすることです。

競技プログラミングのペナルティについて

競技プログラミングではコードを提出するとジャッジされ様々なフィードバックが返ってきます。詳しくはAtCoderのサイトを見てみてください。ここでは一部を紹介します。

AC以外の結果が出た場合、その結果によって何が原因でACされないのかわかるためそれを改善しましょう。解法とプログラムどちらに、またはその両方に欠陥があるのかどうか調べることが大切です。

C++のcoutデバッグ

どこが間違っているかを調べるときにいろいろな箇所を出力しながら確認すると思います。その過程でコードに書かれたcoutを消し忘れてWAしてしまうと悲しい気持ちになるので(自分も何回かして悲しくなりました)消さなくても良いようにすると便利です。そこでデバッグで書いた出力部分を消さなくても大丈夫なようにすると

void debug_out() { cout << endl; }
 
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  cout << H << " ";
  debug_out(T...);
}

#ifdef _DEBUG
#define debug(...) debug_out(__VA_ARGS__)
#else
#define debug(...) 
#endif

これをコードに追加して、出力したいもの下のようにするとデバッグ出力されるようになります。

debug(n); // cout << n << " " << endl;がおこなわれる
debug(n,m,l) // cout << n << " " << m << " " << l << " " << endl;

そしてコンパイル時に下のようにするとデバッグ出力が有効になります。(a.cppの箇所はコンパイルしたいファイル名)

g++ a.cpp -D_DEBUG

これでデバッグ出力箇所の消し忘れをしてもWAにならないようになります。消し忘れをしてしまう人は使ってみてください。出力は自分の好みで変更可能なので可変引数などで調べてみてください。

また、cerrなどで標準エラー出力を用いいる方法もあります。

デバッグ時に気をつけていること

 実際に自分がデバッグ時に確認していることを紹介します。

コンパイル時や実行時にエラーが出ていないか

 エラー文が表示されると思うので読みましょう。どのようなエラーがでているかわからないときなどはエラー文をコピペしてググってみると解決の糸口が見つかるかもしれません。

計算量は大丈夫か

 計算量が大きいとTLEしてしまうため計算量が制限時間内に収まるか確認しましょう。具体的には2secの場合、計算量が106 〜 107 程度だとおおよそ間に合います。それ以上だと厳しいと思っていいと思います(言語や定数倍にもよりますが)。その範囲に落とすことはできないか考えてみましょう。

オーバーフローしていないか

int型の場合、231-1よりも大きい値はオーバーフローしてしまい正確に計算できないためlong long型などを使わないといけません。

Pythonではオーバーフローは起きないため気にしないで良いです。

コーナーケースは踏んでないか

 特定の値やケースの場合のみWAしてしまっていないか確認しましょう。見落としてrateを溶かすことは多々あります。

添え字は間違っていないか

 多次元配列を扱っているときや多重ループをしているときによくしてしまいます。確認しましょう。

小数について

 小数を扱うときは注意が必要です。C++で出力にcoutを使っている場合小数点以下が思うように出力されないことがあります。そのときは

cout << fixed << setprecision(15) << 出力したいもの << endl;

 とすると小数点以下15桁まで出力されるようになるので参考にしてみてください。

最後に

 読んでいただきありがとうございます。一発でコードが思うように動けば最高なんですがうまくいかないことはよくあります。上手にデバッグして思い通りのコードにできるようがんばりましょう!

予告

 明日はOCTPOBさんの記事です。お楽しみに!!!

ebi icon
この記事を書いた人
ebi

競技プログラミングが好きです。

この記事をシェア

このエントリーをはてなブックマークに追加
共有

関連する記事

2023年7月13日
アルゴリズム班はやとき王選手権「競(けい)プロ」を開催しました!
abap34 icon abap34
2021年4月18日
ベズー係数とN項の拡張ユークリッドの互除法
0214sh7 icon 0214sh7
2020年5月15日
【新歓ゲーム制作特集 第2弾】Inverse製作秘話
Saltn icon Saltn
2023年4月29日
CPCTF2023 PPC作問陣 Writeup
noya2 icon noya2
2023年4月21日
CPCTFを開催します
noc7t icon noc7t
2022年8月30日
【競プロer向け】母関数を習得しよう!
tatyam icon tatyam
記事一覧 タグ一覧 Google アナリティクスについて 特定商取引法に基づく表記