chacoderのブログ

競技プログラミングそのほか

自分でランダムケースをつくってバグとりをする方法(Chokudaiさんのツイートから)

Chokudaiさんのツイートから


回答部分と入力部分の分離

まずこんな感じで、回答部分と入力部分を分離して関数家します。こうしてあげるだけで今後の処理がちょっと簡単になる感じ。入力および出力がsolverの中から消えるようにするのがポイント。

f:id:chacoder:20200816225303p:plain

atcoder.jp

比較解法のsolver2をつくって比較テストをする

次に、TLEとなる愚直解solver2を作ります。入力を除外しているので、この時点で愚直解と比較したいろんなテストが出来ます。
この時点で怪しい入力をいくつか試して、答えが合わない解が見つけられたら勝ち。

Submission #15986762 - AtCoder Beginner Contest 175


f:id:chacoder:20200816225559p:plain


f:id:chacoder:20200816225621p:plain

ランダムテストをためす

もし見つけられなかった場合は、一回入力を捨ててランダムテストをたくさん試しましょう。
愚直解はKが大きいと動かないので、Kを小さくしてランダムで動かしてみる感じ。答えが一致したらスルー、一致しなかったらそれを出力、って感じにすると良い。
こうするとダメな時の解が見つけられて良い感じ!

Submission #15987037 - AtCoder Beginner Contest 175

f:id:chacoder:20200816225811p:plain

f:id:chacoder:20200816225838p:plain

OKしかでなかった場合は?

これで例えばX,Dも小さい範囲で試すと実は動いちゃうんだけど、OKしか出なかった場合は、
・そもそも愚直解の考え方or実装が間違っている
・大きいケースでだけ動かない(=9割以上オーバーフロー)
のどっちかなので、どちらかを疑えばOK。考えることが減って嬉しくなる感じ。

ランダムつくるところだけ

自分でランダムケースつくってためすときに、自分で大きな数次々試すのは大変だなと思ってたので、テストケースを乱数で生成して試すのはなるほどでした。

乱数の作り方を知らなかったのでその部分だけ再掲します。

#include <bits/stdc++.h>
using namespace std;

int main(){
  random_device seed_gen;
  mt19937_64 engine(seed_gen());
  for(int i=0;i<100;i++){
    long long x= engine() % (long long)1e15 +1;
    cout<<x<<endl;
  }
  return 0;
}