数据生成&对拍 Windows&Linux
前言
- 对拍是个非常好用的工具,无论在 OI 还是常规情境下,是一个检测代码正确性的工具
数据生成
- C++ 包含一个随机数据生成函数
rand(),支持生成 [0,MAX_RAND] 的随机数,使用srand()设定种子以保证随机性,否则为伪随机,time(0)返回自 1970.1.1 00:00 起到现在经过的秒数,常作为随机种子,如srand(time(0)) - 一般我们像下面那样造数据
int rd(int x) {return (long long)rand()*rand()%x+1;}
- 或者这样
random_device sd;
mt19937 mk(sd());
int myrand(int l,int r)
{
uniform_int_distribution<>dis(l,r);
return dis(mk);
}
- 这个东东是 2K22 教我的,具体什么原理我也不清楚,一般常用上面的造数据
示例:gen.cpp
#include<bits/stdc++.h>
using namespace std;
int rd(int x) {return (long long)rand()*rand()%x+1;}
int main()
{
// freopen("data.in","w",stdout);
/*如果在 Windows 下这个是要非注释*/
/*因为msjing Windows 写的是 C++ 的 chk,而 Linux 写的是脚本*/
srand(time(0));
int m=rd(5);
cout << m << '\n';
return 0;
}
对拍准备
- 对拍操作需要正解代码(暴力也行,就是跑的慢,OI 比赛中常用暴力代码)和待测的代码,没啥注意的,就是常规代码,Windows下要加
freopen
std
示例:std.cpp
#include <bits/stdc++.h>
using namespace std;
int main()
{
// freopen("data.in","r",stdin);
// freopen("std.out","w",stdout);
/*同上*/
//暴力代码
return 0;
}
my
示例:my.cpp
#include <bits/stdc++.h>
using namespace std;
int main()
{
// freopen("data.in","r",stdin);
// freopen("my.out","w",stdout);
/*同上*/
//代码
return 0;
}
对拍程序
-
当然,对拍最重要的是对拍程序,可以大幅减少我们时间开销(我觉得你应该不想手动运行数据生成,正解,待测代码并一个一个对输出)
-
Windows msjing写的是 C++ 程序,Linux msjing写的脚本
-
对拍发现文件不一致后,直接退出程序,数据,std 输出,my 输出都会存储到文件里
-
示例:chk on Windows
-
如果编译的指令跑不了的话,你就只能手动编译运行了,但是只需要运行一次
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n=500;//500组
system("g++ gen.cpp -o gen.exe -std=c++14 -O2");
system("g++ std.cpp -o std.exe -std=c++14 -O2");
system("g++ my.cpp -o my.exe -std=c++14 -O2");
/*编译*/
for (int i=1;i<=n;i++)
{
system("gen.exe");
system("std.exe");
system("my.exe");
/*运行*/
if (system("fc a.out a.ans"))/*文件比较*/
{
puts("Wrong Answer");
return 0;
}
printf("AC on test case %d\n",i);
}
return 0;
}
-
示例:chk on Linux
-
写的脚本,C++ 也行
-
脚本需要存在 .sh 文件里而不是 .cpp
#!/bin/bash
echo "Compiling programs..."
g++ gen.cpp -o gen -O2 -std=c++14
g++ std.cpp -o std -O2 -std=c++14
g++ my.cpp -o my -O2 -std=c++14
if [ $? -ne 0 ]; then
echo "Compile Error"
exit 1
fi
echo "successful"
count=0
while true; do
count=$((count + 1))
echo "Testing case $count..."
./gen > data.in
./std < data.in > std.out
./my < data.in > my.out
if ! diff -q std.out my.out > /dev/null; then
echo "************************************"
echo "case $count is Wrong!"
echo "************************************"
exit 0
else
echo "Case $count Accept!"
fi
done
- from
毕竟msjing不会写脚本- Linux 由于使用脚本,所以直接写代码,不用
freopen - 如果提醒你权限不够,使用
chmod +x chk.sh增加运行权限 - 使用
./chk.sh直接开始
扩展
获取运行时间
- 使用 C++ 中clock
double stime = clock();
double etime = clock();
cerr << (etime-stime)/CLOCKS_PER_SEC << endl;
// cerr是错误输出流,可以把时间直接打到控制板上
附:生成图
- LZY说有锅?
code
#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=10010;
int random(int n)
{
return (long long)rand()*rand()%n;
}
pair<int,int> e[maxn];
map<pair<int,int>,bool> h;
int main()
{
// freopen("1.in","w",stdout);
srand(time(0));
int n=random(15),m=random(15);
while (!n) n=random(15),m=random(15);
printf("%d %d\n",n,m);
for (int i=1;i<n;i++)
{
int fa=random(i)+1;
e[i]=make_pair(fa,i+1);
h[e[i]]=h[make_pair(i+1,fa)]=1;
}
for (int i=n;i<=m;i++)
{
int x,y;
do
{
x=random(n)+1,y=random(n)+1;
}while (x == y || h[make_pair(x,y)]);
e[i]=make_pair(x,y);
h[e[i]]=h[make_pair(y,x)]=1;
}
random_shuffle(e+1,e+1+m);
for (int i=1;i<=m;i++) printf("%d %d\n",e[i].first,e[i].second);
return 0;
}

浙公网安备 33010602011771号