对拍

· · 个人记录

windows

#include<bits/stdc++.h>
#include<ctime>
using namespace std;
int main(){
    while(1){
        system("data.exe");
        system("baoli.exe");
        system("std.exe");
        if(system("fc std.out baoli.out")) break;
    }
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
int main(){
    struct _timeb T;
    _ftime(&T);
    srand(T.millitm);
    freopen("1.in","w",stdout);
}

linux

```cpp
#include <bits/stdc++.h>

int main() {
    system("rm 1; rm a; rm b; make 1 && make a && make b");//把每个程序先编译一下
    int t = 0; 
    while (1) {//这里设置的是无限循环,直到出现错误,也可以限制次数
        printf("#%d------->", ++t);//方便查看
        system("./1 > in");//将生成的数据放到in中
        //system("python3 1.py > in");//用python造数据
        system("./a < in > a.out");//从in中读取放到out中
        system("./b < in > b.out");
        if (system("diff a.out b.out"))//比较两个输出,diff若不相同返回1
            return system("gnome-terminal -x bash -c echo 'Wrong Answer'"), 0;//弹出窗口提示并结束程序
        puts("Accepted");
    }
}

鉴于NOI系列赛事在~~辣鸡~~NOI LINUX环境进行,特地对linux下对拍进行了一下学习。在此分享。

以下内容中的文件名解释:
- pai 对拍
- gen 数据生成(生成到test.in)(将在下篇博文具体介绍)
- test 进行对拍的程序的可执行文件(从test.in读入,输出到test.out)
- std 用来对拍的程序的可执行文件(通常为暴力或其他正确的做法)(从test.in读入,输出到test.ans)

## 一个熟练的C++选手

C++作为一个高级语言,可移植性本身就很好,所以这个方法对于所有平台通用。

只需要将以下程序和test、std放在一个目录内编译运行即可。

```cpp
#include <bits/stdc++.h>

using namespace std;

void gen()
{ ... } //数据生成,下篇博文中具体介绍

int main()
{
    while(true) {
        gen();//也可以自己再写一个gen.cpp编译后使用如下system()运行,以下不需要输出到stderr
        system("./test"); //windows环境不需要加./,下同
        system("./std");

        if(system("diff test.out test.ans")) { //windows下可以使用fc代替diff
            fprintf(stderr, "WA\n");
            getchar();
        } else
            fprintf(stderr, "AC\n");

        //注意,由于前面gen()中可能使用freopen()对stdout进行了重定,所以不能直接使用printf();如需使用,请在gen()结束后使用如下命令:
        //windows下: freopen("CON", "r", stdin);
        //Linux下: freopen("/dev/console", "r", stdin);
        //以下是spj的例子
        /*一个实数比较的例子,精确到1e-6.
        ifstream out("test.out"), ans("test.ans");
        double a, b;
        out >> a;
        ans >> b;
        if(fabs(a - b) > 1e-6) {
            fprintf(stderr, "WA read: %lf expected: %lf\n", a, b);
            getchar();
            goto ed;
        }
        fprintf(stderr, "AC\n");
        ed: ;
        */
    }

    return 0;
}

一个linux用户

类似于windows下的.bat批处理文件,linux下也可以自行使用脚本进行对拍。

将以下文件保存为.sh(本文为pai.sh),和gen、test、std保存在同一目录下(假设该目录为~/Desktop/AH-2333/test/)。

while true; do
./gen
./test
./std
if diff test.out test.ans; then
echo AC
else
echo WA
exit 0
fi
done

运行时只需要在~/Desktop/AH-2333/test/目录下启动终端(NOI LINUX貌似把这个功能删了,可能需要打开终端手动cd到指定目录,这时可以使用tab键自动补全目录,注意,linux下大小写敏感),然后输入sh pai.sh即可。

最后退出时的.in/.out/.ans即为拍出错误的文件。

如果需要spj,则不能使用系统自带的diff,可以自己手写一个spj.cpp,编译后,将以上的if diff test.out test.ans;改成if ./spj即可。spj的写法如下:

#include <bits/stdc++.h>

using namespace std;

int main()
{
    ifstream out("test.out"), ans("test.ans");
    double   a, b;
    out >> a;
    ans >> b;
    return fabs(a - b) > 1e-6 ? 1 : 0; //0为真
}