Loading

关于Linux环境下的对拍

关于Linux环境下的对拍

前言

  • 在OI竞赛中,日常训练Debug以及考场上验证正解的正确性,我们经常将自己的 Bug 代码和同学的正确性未知的代码做人眼比对,咳咳,当然不,还是要用电脑做对拍,效率更高,查错更快。

Method

  • 显然,我们需要四组代码,一个亟待Debug的代码,一组正确代码,一组随机数生成器(后续),以及对拍程序。
  • 以信息竞赛经典算法——排序(据说可能面试要用?)为例,我们用到sort冒泡排序,详情见代码块。
  • std.cpp
    int main(){
        freopen("std.out", "w", stdout);
    	cin >> n;
    	for(int i = 1; i <= n; i++)
    		cin >> a[i];
    	sort(a + 1, a + 1 + n);//stable_sort同理
    	for(int i = 1; i <= n; i++)
    		cout << a[i] << " ";
    	return 0;
    }
    
    
  • tmp.cpp
    int main(){
        freopen("tmp.out", "w", stdout);
    	cin >> n;
    	for(int i = 1; i <= n; i++)
    		cin >> a[i];
    	for(int i = 1; i <= n; i++)
    		for(int j = i + 1; j <= n; j++)
    			if(a[i] > a[j])	swap(a[i], a[j]);
    	for(int i = 1; i <= n ;i++)
    		cout << a[i] << " ";
    	return 0;
    }
    
    
  • rand.cpp
    关于数据生成,每道题需要的数据不一样,
    #include <iostream>
    #include <ctime>//rand函数需要
    #include <algorithm>
    using namespace std;
    
    int main(){
        freopen("rand.out", "w", stdout);
    	srand(time(NULL));
    	int n = rand() % 10 + 1;
    	cout << n << endl;
    	while(n--){
    		int a = rand() % 100 + 1;
    		cout << a << " ";
    	}
    	cout << endl;
    }
    
    
  • dp.cpp
    由于要进行大量的比对操作,所以选择使用文件对比,否则就失去了对拍的意义
    #include <algorithm>
    using namespace std;
    int main(){
    	int T = 10000;
    	int tot = 0;
    	while(T--){
    		tot++;
    		cout << tot << " ";
    		system("./rand; ./std; ./tmp");
    		if(system("diff std.out tmp.out")){
    			cout << "WA" << endl;
    			return 0;
    		}
    		else cout << "AC" << endl;
    	}
    }
    
    
    上述代码运行时,运行了文件对比函数diff,当两个文件不完全一致时,返回结果true,此时输出“WA”且程序停止运行,将hack数据保存在rand.out中,以便手模查错。

后续——浅析rand随机数生成函数

  • 这里的数据生成程序是调用的外部程序, 每个数据点都重新运行, 而在linux系统上, time(0)会返回当前时间戳, 即从1970年1月1日0点0分0秒到现在经过的秒数, 所以每秒time(0)的返回值不变, 作为随机数种子时, 每秒内生成的数据也都相同, 那么该怎么修改呢?
  • 首先我们要知道linux系统上一个特殊的设备/dev/urandom, 它提供永不为空的随机二进制数据流, 当然还有更随机的/dev/random。但是/dev/random为了保证随机性可能会中断输出, 相比之下, /dev/urandom不会导致程序堵塞。
  • 更多信息参见内核熵池

实际应用时, 把/dev/urandom当作一个文件, 使用freopen读入

freopen("/dev/urandom", "r", stdin);  

然后初始化随机数种子时, 使用getchar()读入:

srand(getchar()*getchar()*getchar()*time(0));

11.23UPD

\(Shell\)

make data
make 001
make 002

((cnt=1))

while true
do
	./data > in
	./001 < in > 1.out
	./002 < in > 2.out
	if diff 1.out 2.out; then
		printf "# $((cnt++)) Accepted\n";
	else 
		notify-send "Gary"
		break
	fi
done
posted @ 2020-07-15 17:36  Gary_818  阅读(1755)  评论(3编辑  收藏  举报