一般在做题时,会被一些数据卡住,除了边界数据外,很多数据是随机生成的,为了适配普遍情况的随机数据。
但是在线评测系统(OJ)一般不公开测试数据,这是一个OJ 的命脉。
做题的时候,时常会很难造出来一些数据,这时候,就可以随机生成数据,再用一个已知正确的做法去对比答案(如果有std,则可以采用std,否则可以自己写一个暴力的做法,暴力虽然不能通过题目,但是可以帮助我们debug)。
下面是一个对拍程序的几个部分:
- 数据生成器:
gen 
- 需要debug的代码 
my.cpp 
- 已知正确的代码 
std.cpp 
- 运行程序并对比答案的脚本 
check.sh 
题目
求解 $A \times B$ ,其中 A 和 B 都是 $32$ 位有符号整数。
my.cpp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  | 
#include <iostream>
int main()
{
    int a, b;
    std::cin >> a >> b;
    std::cout << a * b << std::endl;
    
    return 0;
}
  | 
 
std.cpp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  | 
#include <iostream>
int main()
{
    long long a, b;
    std::cin >> a >> b;
    std::cout << a * b << std::endl;
    
    return 0;
}
  | 
 
gen
1
2
3
4
5
6
  | 
#!/usr/bin/python3
import random
a = random.randint(-2**31, 2**31-1)
b = random.randint(-2**31, 2**31-1)
print(a, b)
  | 
 
check.sh
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
  | 
#!/bin/bash
g++ -std=c++11 std.cpp -o std
g++ -std=c++11 my.cpp -o my
for((i=1;i<=100;i++))
do
  ./gen > gen.in
  ./std < gen.in > std.out   # 计算正确答案
  ./my < gen.in > my.out     # 计算待测试算法的输出结果
  if diff -w std.out my.out > /dev/null; then
    echo "Test $i: AC"
  else
    echo "Test $i: WA"
    exit 0
  fi
done
echo "All tests passed"
  | 
 
写好后,运行 check.sh 。
运行多次,结果如下:

可以发现几乎都是在 Test1 就发现了错误的数据,这得益于这道题的数据很好溢出。
一般来说,如果一次执行不成功,可以尝试多次,如果多次都不成功,可能问题不在于普通数据上,需要考虑边界数据了。
发现错误后
发现了 WA 后,去当前路径下的 gen.in 中得到数据,并进行 debug 。一般来说,数据不要太大,否则不好 debug 。