对拍Bete

前言

那天LZY需要对拍,题目样例给的是一个图,LZY发现自己的对拍程序并不能生成图。
这时候msjing站出来说:

我有随机生成图的程序。

这么好?
于是我直接拿来用。
用着用着不对劲。

  • 你这图生成的什么玩意?
  • msjing不知道

靠别人不如靠自己,在我坚持了3.1415926个小时后,终于写成了一个较为强大的随机样例生成器,大部分常用生成器均已打包进了函数里。

完整对拍程序

下载

注意:这个有亿点锅。

版本(胡扯) 系统 语言 大小 下载 备注
2.0(开源) Windows C++14及以上 1.35 MB 对拍2.0(开源).zip 这个纯粹是因为没有教程而发的
2.0(用户版) Windows C++14及以上 1.34MB 对拍2.0(用户版).zip 教程正在筹备,有能力的可以下载开源版自己摸索
以下版本有适配性问题 以下版本下载链接失效 这个锅我到现在才意识到
1.2.0(测试) Windows C++14及以上 1.18 MB 对拍1.2.0(测试).zip 可以下载
1.1.5(测试) Windows C++14及以上 907.15 KB 对拍1.1.5(测试).zip 跟前一个版本没什么变化
1.1.4(正式) Windows C++14及以上 907.08 KB 对拍1.1.4(正式).zip 稳定,可以下载
1.1.3(正式) Windows C++14及以上 903.25 KB 对拍1.1.3(正式).zip 跟后一个版本没什么变化
1.1.2(测试) Windows C++14 904.55 KB 对拍1.1.2(测试).zip 锅最多的版本
1.1.1(正式) Windows C++14 903.12 KB 对拍1.1.1正式版.zip 老,啥也没有

有人跟我犟,说我就要用1.2.0及以前的版本。
其实源文件并没有删,把链接复制过来,在在里面加上“对拍”两个字,就可以下了。

错误链接:
https://files.cnblogs.com/files/blogs/870368/1.2.0(测试).zip?t=1786588525&download=false

正确链接:
https://files.cnblogs.com/files/blogs/870368/对拍1.2.0(测试).zip?t=1786588526&download=true

然后发现这个东西出了作者在的机房电脑可以用,其他电脑上的那个快捷方式都是假的,只能去文件夹里把原文见打开。

在2.0以及后续版本不会出现这种问题(应该),可以放心使用。

另外,开源版本设有密码,可以打开源文件自行查找,也是作者给的一个小小考验qwq。

使用教程[以2.0(用户版)为准]

  • 首先最重要的一步是,你要把它下下来。

  • 然后暴力解压,到哪去都行。

  • 打开那个“对拍-用户版”文件夹,可以看到一个“启动!.bat”文件,双击运行它(不保证不同电脑中文显示不会出现乱码的情况)。

  • 然后一个黑框框一闪而过然后打开了另一个黑框框,你就可以在上面输入指令运行了。

下面说一下每一个指令及作用
  • start
    这是开始对拍的指令。
    输入 “start <num>” 后,程序会进行 <num> 次对拍。

  • close
    这个是用来停用一些功能的。
    具体什么功能?

    1. “G” 可以停用 “Generator”。
    2. “A” 可以停用 答案程序。
    3. “U” 可以停用 用户程序。
    4. “all” 可以停用上面三个。
    5. “auto” 可以停用 自动编译。

    输入“close <option>”即可使用。

  • need
    这个跟上面相反,是用来启用一些功能的。
    用法一样,选项一样。

    输入“need <option>”即可使用。

  • open
    不要整错了,这个是用来打开文件夹的。

    1. “G” 可以打开 “Generator” 文件夹。
    2. “A” 可以打开 答案程序 文件夹。
    3. “U” 可以打开 用户程序 文件夹。
    4. “C” 可以打开 “Checker” 文件夹。
    5. “all” 可以打开上面四个。
    6. “P” 可以打开 “program” 文件夹。
    7. “WA” 可以打开 “WA-input” 文件夹。

    每个文件夹作用在后面会说的,不要着急。

    输入 “open <option>” 即可使用。

  • show
    用于查看当前的配置信息。

    1. “name” 可以查看 程序名称及输入输出文件名 。
    2. “path” 可以查看 程序相对路径。
    3. “need” 可以查看 启用/停用 情况。
    4. “compile” 可以查看 编译指令。

    输入 “show <option>” 即可使用。

  • change
    要是只能看不能改哪还有什么意思?

    输入 “change”+回车 按照指示写就行(其实所有指令都有指示)。

  • save
    费好大劲整完了一不小心关掉了然后就要重新配置,因为作者懒所以出了个保存功能。
    输入 “save <plan name>” 即可将当前的配置保存到 “<path name>” 中。

  • apply
    是上一个的孪生兄弟,用于应用已经保存好的方案。
    输入 “apply <plan name>” 即可应用 “<path name>” 配置。

  • 命令行
    另外,如果你输入的指令是上面没有的话,程序会让命令行去运行。
    比如你输入了一个 “cls”,会清空屏幕。

  • 使用 “open” 指令分别打开 “A”、“U”,然后你可一进行一下任意一种操作:

    • 将代码粘到事先准备好的 “.cpp” 文件中。
    • 将代码文件扔到那个文件夹里。
    • 或者简单粗暴,直接将编译好的 “.exe” 文件扔进去。
  • 使用 “open” 打开 “G” 在 “Generator.cpp” 里面生成数据。

  • 若有 “Special Judge” ,使用 “open” 打开 “C”,然后你可一进行一下任意一种操作:

    • 在 “Checker.cpp” 中自己写一个 “Special Judge”。
    • 直接上传一个 “.exe” 文件,程序会按照 “<checker name>.exe <input> <user's output> <answer ouput>” 的方式运行。
  • 然后使用 “change” 指令调整配置,程序名一定不能加后缀,文件名后缀可加可不加,但一定要与你程序的输入输出文件一致。

  • 最后就可以用 “start” 指令开始对拍。

  • 当出现非WA结果时,这个对拍不会像其他对拍那样直接停掉,而是会将错误测试点输入样例同意放到 “WA-input” 文件夹中,使用 “open WA” 即可打开。

  • 出现RE结果应该会直接停掉,在测试的时候并没有出现RE报错,我也忘了我自己写的什么了qwq;

随机样例生成器

随机样例生成器
#include<bits/stdc++.h>
#include<tuple>
#include<vector>
#define uint unsigned int
#define ll long long
#define ull unsigned long long
#define dbl double
#define TIME chrono::system_clock::now().time_since_epoch().count()
using namespace std;
mt19937_64 num(TIME);

template<typename T>inline T INT(T l,T r,char out=0){T x=num()%(r-l+1)+l;if(out)cout<<x<<out;return x;}
template<typename T>inline vector<T> INT(int len,T l,T r,char out=0,char out2=0){vector<T> v(len);for(int i=0;i<len;++i) v[i]=INT(l,r,out);if(out2) cout<<out2;return v;}

template<typename T>inline T FLO(T l,T r,char out=0,int pos=3){
	uniform_real_distribution<long double> flo(l,r);
	T x=flo(num);
	if(out) cout<<fixed<<setprecision(pos)<<x<<out;
	return x;
}
template<typename T>inline vector<T> FLO(int len,T l,T r,char out=0,char out2=0,int pos=3){
	vector<T> v(len);
	for(int i=0;i<len;++i) v[i]=FLO(l,r,out,pos);
	if(out2) cout<<out2;
	return v;
}

inline char CH(char l,char r,char out=0){char x=num()%(r-l+1)+l;if(out)cout<<x<<out;return x;}
inline char CH(string s,char out=0){char x=s[INT(0,(int)s.size()-1)];if(out)cout<<x<<out;return x;}
inline string STR(int len,char l,char r,char out=0,char out2=0){string s;for(int i=1;i<=len;++i) s+=CH(l,r,out);if(out2) cout<<out2;return s;}

template<typename T> inline T Pick(initializer_list<T> s,char out=0){
	T x=*(s.begin()+num()%s.size());
	if(out) cout<<x<<out;
	return x;
}
template<typename T>inline vector<T> Pick(int len,initializer_list<T> s,char out=0,char out2=0){
	vector<T> v(len);
	for(int i=0;i<len;++i) v[i]=Pick(s,out);
	if(out2) cout<<out2;
	return v;
}

pair<int,int> ITV(int l,int r,char out=0){
	int x=INT(l,r),y=INT(l,r);
	if(x>y) swap(x,y);
	if(out) cout<<x<<' '<<y<<out;
	return {x,y};
}

auto Graph(int point,int edge,int weightl=0,int weightr=0,vector<string> t={}){
	map<string,bool> type;
	for(string s:t) type[s]=1;
	bool repeat=type["repeat"],directed=type["directed"],
	forest=type["forest"],self=type["self"],
	heap=type["max-heap"]|type["min-heap"]|type["heap"];
	vector<tuple<int,int,int> > g;
	map<pair<int,int>,bool> vis;
	vector<int> tmp;
	if(type["max-heap"]) for(int i=point;i>=1;--i) tmp.emplace_back(i);
    else for(int i=1;i<=point;++i) tmp.emplace_back(i);
	if(!heap) shuffle(tmp.begin(),tmp.end(),num);
	if(!forest)
    for(int i=1,x,y;i<(int)tmp.size();++i){
        x=tmp[INT(0,i-1)],y=tmp[i];
        if(!repeat){
			if(directed)vis[{x,y}]=1;
			else vis[{x,y}]=vis[{y,x}]=1;
		}
		g.emplace_back((tuple<int,int,int>){x,y,INT(weightl,weightr)});
    }
	if(!forest) edge-=point-1;
	if(!type["tree"])
	while(edge>0){
		int x=INT(1,point),y=INT(1,point);
		while(vis[{x,y}]||(x==y&&!self)) x=INT(1,point),y=INT(1,point);
		if(!repeat){
			if(directed)vis[{x,y}]=1;
			else vis[{x,y}]=vis[{y,x}]=1;
		}
		g.emplace_back((tuple<int,int,int>){x,y,INT(weightl,weightr)});
		edge--;
	}
	if(type["value"]) for(auto x:g)cout<<get<0>(x)<<' '<<get<1>(x)<<' '<<get<2>(x)<<'\n';
	else if(type["out"]) for(auto x:g)cout<<get<0>(x)<<' '<<get<1>(x)<<'\n';
	return g;
}

void Generate(){
	//write here!!!!!!!!!!!!!!!! 
	
}

signed main(int argn,char* argv[]){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	if(argn==2) freopen(argv[1],"w",stdout);
	Generate();
	return 0;
}

使用教程[以2.0(用户版)为准]

随机生成整数INT()

使用INT()函数可以随机生成整数,返回值类型与传入参数 \(l,r\) 有关。

函数参数:

\[INT(l,r,out) \]

随机生成整数,返回一个整数。

  • \(l,r\) (必要参数)表示生成随机数的范围 \([l,r]\)。
  • \(out\) (非必要参数)表示是否输出及输出类型,默认为 \(0\),即不输出,若传入「空格」则表示将生成的随机数输出并输出后输出「空格」。

\[INT(len,l,r,out,out2) \]

生成随机整数数列,返回一个vector。

  • \(len\) 表示生成随机数列的长度。
  • \(l,r\) 同上。
  • \(out\) 表示数列中每一个数的输出类型,默认为 \(0\)。
  • \(out2\) 表示整个序列的输出类型,默认为 \(0\)。

注意:

为避免传参混乱的问题,请不要写类似 \(INT(int,int,int)\) 的传参。

随机生成浮点数FLO()

使用FLO()函数可以生成随机浮点数,返回值类型与 \(l,r\) 有关。

函数参数:

\[FLO(l,r,out,pos) \]

随机生成浮点数,返回一个浮点数。

  • \(l,r,out\) 同上。
  • \(pos\) 表示输出时小数的位数。

\[FLO(len,l,r,out,out2,pos) \]

生成随机浮点数数列,返回一个vector。

  • \(len,l,r,out,out2,pos\) 同上。

随机生成字符(串)CH()/STR()

使用CH()函数可以生成一个字符,STR()可以生成一个字符串。

函数传参:

\[CH(l,r,out) \]

生成一个字符,返回char。

  • \(l,r,out\) 同上。

\[STR(len,l,r,out,out2) \]

生成一个字符串,返回一个string。

  • \(len,l,r,out,out2\) 同上。

随机选择Pick()

使用Pick()可以在一个有限集合内选择元素。

函数传参:

\[Pick(s,out) \]

在集合中选择一个元素,返回该元素。

  • \(s\) 传入的集合,集合内元素使用花括号{}包裹,逗号分割。
  • \(out\) 同上。

\[Pick(len,s,out,out2) \]

多次随机选择元素组成一个元素列,返回一个vector。

  • \(len,s,out,out2\) 同上。

随机生成区间ITV()

使用ITV(),随机生成一个区间。

函数传参:

\[ITV(l,r,out) \]

生成 \([l,r]\) 的一个子区间,返回一个pair<int,int>。

  • \(l,r\) 区间范围。
  • \(out\) 同上。

随机生成图Graph()

使用Graph函数可以快速生成一个图。
完整参数如下。
Graph(int point,int edge,int weightl=0,int weightr=0,vector<string> t={})。

  • point 表示节点数。
  • edge 表示边数。
  • weightl与weightr 表示权值的范围。

最后的vector<string> t={}表示指令。

  • tree 指令可以让函数强制生成一颗树,只在乎节点数,不在乎边数。
  • forest 指令允许函数生成的图不连通,即森林。
  • directed 指令会使函数认为\(x \rightarrow y\)与\(y \rightarrow x\)不是一条边,即生成有向图。
  • out 指令可以让函数直接将这颗树输出。
  • value 指令可以让函数输出时额外输出边权。
  • repate 指令可以允许函数生成重边。
  • self 指令可以允许函数生成自闭环。
  • heap 类命令可以让函数生成的树满足堆性质,默认为小根堆,min-heap、max-heap分别对应小根堆、大根堆。
auto g=Graph(10,10); //生成10个节点10条边的基环树。
auto g=Graph(10,100,1,1000,{"value","repeat","forest"});
//生成一个10个节点100条边、可重边、权值在 1~1000 之间的带边权的无向图,并带权输出,同时将图返回给变量 g。其中允许生成的图不连通。

注意

  • 若你不传任何指令,函数默认生成一个不重边、无自闭环的无向联通图,返回值类型为vector<tuple<int,int,int> >,tuple中的三个元表示 边与权值。

  • 此生成随机图函数为不完整版,生成速度较慢,请不要使用它生成规模 \(1e5\) 以上的树,若要生成 \(1e6\) 规模的图请加上 forest 和 repeat 指令。

  • 若没有forest指令,函数会先生成一颗树,再在树的基础上加边,也就是说如果传入的边数小于节点数减一,那么函数将返回一颗树。

  • 若没有repeat指令,传入的边数远远大于节点数的话,函数会四掉的。

  • 仍要注意的是无论你是否选择输出,函数都会将图返回。

开源代码

Lancher

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

void color(int c){
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(handle, c);
}
void print(string s,int col){
	color(col);
	cerr<<s;
	color(7);
}

bool isNum(string s){
	if(s=="") return 0;
	for(char x:s) if(x<'0'||x>'9') return 0;
	return 1;
}

void Getline(istream& in,string &s){
	char x=in.get();s="";
	while(x=='\n') x=in.get();
	while(x!='\n') s+=x,x=in.get();
}
void Getline(ifstream& in,string &s){
	char x=in.get();s="";
	while(x=='\n') x=in.get();
	while(x!='\n') s+=x,x=in.get();
}

string test_num="10";
bool auto_compile=1;
string compile="-std=c++14 -o2";

bool need_Generator=1,need_Answer=1,need_User=1;

char need_[]="TTT";
string show_name[10]={
	"Generator     ",
	"User's program",
	"Answer progeam",
	"Checker       ",
	"Sample input  ",
	"User's output ",
	"Answer output "
};
string name_[10]={
	"Generator",
	"User",
	"Answer",
	"Checker",
	"input.in",
	"output.out",
	"output.ans"
};
string path_[10]={
	"program\\generator\\",
	"program\\user\\",
	"program\\answer\\",
	"program\\checker\\",
	"..\\..\\"
};

string merge(){
	string tmp="Leader.exe "+(string)need_;
	for(int i=0;i<7;++i) tmp+=' '+name_[i];
	for(int i=0;i<5;++i) tmp+=' '+path_[i];
	return tmp+' '+test_num;
}

bool check(){
	ifstream G,U,A,C;
	G.open(path_[0]+name_[0]+".exe");
	U.open(path_[1]+name_[1]+".exe");
	A.open(path_[2]+name_[2]+".exe");
	C.open(path_[3]+name_[3]+".exe");
	bool f=0;
	if(!G.is_open()&&need_[0]=='T'){
		ifstream tmp(path_[0]+name_[0]+".cpp");
		if(tmp.is_open()) system(("g++ "+compile+" -o "+path_[0]+name_[0]+".exe "+path_[0]+name_[0]+".cpp").c_str());
		else print("Can't compile "+name_[0]+".cpp\n",7),f=1;
	}
	if(!U.is_open()&&need_[1]=='T'){
		ifstream tmp(path_[1]+name_[1]+".cpp");
		if(tmp.is_open()) system(("g++ "+compile+" -o "+path_[1]+name_[1]+".exe "+path_[1]+name_[1]+".cpp").c_str());
		else print("Can't compile "+name_[1]+".cpp\n",7),f=1;
	}
	if(!A.is_open()&&need_[2]=='T'){
		ifstream tmp(path_[2]+name_[2]+".cpp");
		if(tmp.is_open()) system(("g++ "+compile+" -o "+path_[2]+name_[2]+".exe "+path_[2]+name_[2]+".cpp").c_str());
		else print("Can't compile "+name_[2]+".cpp\n",7),f=1;
	}
	if(!C.is_open()){
		ifstream tmp(path_[3]+name_[3]+".cpp");
		if(tmp.is_open()) system(("g++ "+compile+" -o "+path_[3]+name_[3]+".exe "+path_[3]+name_[3]+".cpp").c_str());
		else print("Can't compile "+name_[3]+".cpp\n",7),f=1;
	}
	return f;
}
string oder[100];
int tot=1;
void translate(string s){
	for(int i=1;i<=tot;++i) oder[i]="";
	tot=1;int len=s.length();
	for(int i=0;i<len;++i){
		if(s[i]==' '){
			if(oder[tot].length()) oder[++tot]="";
			continue;
		}
		oder[tot]+=s[i];
	}
}
void Compile(){
	ifstream G,U,A;
	G.open(path_[0]+name_[0]+".cpp");
	U.open(path_[1]+name_[1]+".cpp");
	A.open(path_[2]+name_[2]+".cpp");
	if(G.is_open()&&need_[0]=='T') system(("g++ "+compile+" -o "+path_[0]+name_[0]+".exe "+path_[0]+name_[0]+".cpp").c_str());
	if(U.is_open()&&need_[1]=='T') system(("g++ "+compile+" -o "+path_[1]+name_[1]+".exe "+path_[1]+name_[1]+".cpp").c_str());
	if(A.is_open()&&need_[2]=='T') system(("g++ "+compile+" -o "+path_[2]+name_[2]+".exe "+path_[2]+name_[2]+".cpp").c_str());
}

void save_plan(string name){
	if(opendir("plans")==NULL){
		mkdir("plans");
	}
	ofstream fout("plans\\"+name);
	for(int i=0;i<7;++i) fout<<name_[i]<<'\n';
	for(int i=0;i<5;++i) fout<<path_[i]<<'\n';
	fout<<compile<<'\n';
	fout<<need_<<'\n';
	fout<<auto_compile<<'\n';
}
void apply_plan(string name){
	ifstream fin("plans\\"+name);
	if(!fin.is_open()){
		cout<<">Can't find "+name<<'\n';
		return;
	}
	for(int i=0;i<7;++i) fin>>name_[i];
	for(int i=0;i<5;++i) fin>>path_[i];
	Getline(fin,compile); 
	fin>>need_;
	fin>>auto_compile;
}

void lock(){
	string password;
	while(cin>>password&&password!="237051146");
	cout<<"Unclocked!\n";
	system("pause");
	system("cls");
}

signed main(){
	lock();
	string s;
	cout<<">>";
	while(getline(cin,s)){
		translate(s);
		if(oder[1]=="start"){
			test_num=oder[2];
			if(test_num==""){
				cout<<"<times>";
				cin>>test_num;
			}
			if(check()) goto nxt;
			if(auto_compile) Compile();
			system(merge().c_str());
		}else
		if(oder[1]=="close"){
			if(oder[2]==""){
				cout<<"\tG: Generator\t"<<(need_[0]=='T'?"true":"false")<<'\n';
				cout<<"\tU: User     \t"<<(need_[1]=='T'?"true":"false")<<'\n';
				cout<<"\tA: Answer   \t"<<(need_[2]=='T'?"true":"false")<<'\n';
				cout<<"\tauto: Automatic compilation\t"<<(auto_compile?"true":"false")<<'\n';
				cout<<"\tall: G,U and A\n";
				cout<<"<option>";
				cin>>oder[2];tot=2;
			}
			for(int i=2;i<=tot;++i){
				if(oder[i]=="G") need_[0]='F';
				else if(oder[i]=="U") need_[1]='F';
				else if(oder[i]=="A") need_[2]='F';
				else if(oder[i]=="All") need_[0]=need_[1]=need_[2]='F';
				else if(oder[i]=="auto") auto_compile=0;
				else cout<<">What is \""+oder[i]+"\" ?\n";
			}
		}else
		if(oder[1]=="need"){
			if(oder[2]==""){
				cout<<"\tG: Generator\t"<<(need_[0]=='T'?"true":"false")<<'\n';
				cout<<"\tU: User     \t"<<(need_[1]=='T'?"true":"false")<<'\n';
				cout<<"\tA: Answer   \t"<<(need_[2]=='T'?"true":"false")<<'\n';
				cout<<"\tauto: Automatic compilation\t"<<(auto_compile?"true":"false")<<'\n';
				cout<<"\tall: G,U and A\n";
				cout<<"<option>";
				cin>>oder[2];tot=2;
			}
			for(int i=2;i<=tot;++i){
				if(oder[i]=="G") need_[0]='T';
				else if(oder[i]=="U") need_[1]='T';
				else if(oder[i]=="A") need_[2]='T';
				else if(oder[i]=="all") need_[0]=need_[1]=need_[2]='T';
				else if(oder[i]=="auto") auto_compile=1;
				else cout<<">What is \""+oder[i]+"\" ?\n";
			}
		}else
		if(oder[1]=="open"){
			if(oder[2]==""){
				cout<<"\tG   : Generator\n";
				cout<<"\tU   : User's\n"; 
				cout<<"\tA   : Answer\n";
				cout<<"\tC   : Checker\n";
				cout<<"\tWA  : input of WA\n";
				cout<<"\tP   : Programs\n";
				cout<<"\tallP: G,U,A and C\n";
				cout<<"<option>";
				cin>>oder[2];tot=2;
			}
			if(oder[2]=="allP"){
				tot=6;
				oder[2]="G";oder[3]="U";oder[4]="A";
				oder[5]="C";
			}
			for(int i=2;i<=tot;++i){
				if(oder[i]=="G") system("start program\\generator");
				else if(oder[i]=="U") system("start program\\user");
				else if(oder[i]=="A") system("start program\\answer");
				else if(oder[i]=="C") system("start program\\checker");
				else if(oder[i]=="WA") system("start WA-input");
				else if(oder[i]=="P") system("start program");
				else cout<<">What is \""+oder[i]+"\" ?\n";
			}
		}else
		if(oder[1]=="show"){
			if(oder[2]==""){
				cout<<"<name/path/need/compile/plan>";
				cin>>oder[2];tot=2;
			}
			if(oder[2]=="all"){
				tot=5;
				oder[2]="name";
				oder[3]="path";
				oder[4]="need";
				oder[5]="compile";
			}
			if(oder[2]=="plan"&&oder[3]==""){
				cout<<"<plan name>";
				cin>>oder[3];tot=3;
			}
			if(oder[2]=="plan"){
				ifstream fin("plans\\"+oder[3]);
				if(!fin.is_open()){
					cout<<">can't find "+oder[3]<<'\n';
					goto nxt;
				}
				string tmp;
				for(int i=0;i<7;++i){
					fin>>tmp;
					cout<<'\t'<<show_name[i]<<":\t"<<tmp<<'\n'; 
				}
				for(int i=0;i<4;++i){
					fin>>tmp;
					cout<<'\t'<<show_name[i]<<":\t"<<tmp<<'\n';
				}
				fin>>tmp;
				cout<<"\tChecker to program:\t"<<tmp<<'\n';
				Getline(fin,tmp);
				cout<<"\tCompile command:\t"<<tmp<<'\n';
				char tmp_;
				for(int i=0;i<3;++i){
					fin>>tmp_;
					cout<<'\t'<<show_name[i]<<":\t"<<(tmp_=='T'?"true\n":"false\n");
				}
				fin>>tmp_;
				cout<<"\tAutomatic compilation\t"<<(tmp_=='1'?"true\n":"false\n");
			}else
			for(int i=2;i<=tot;++i){
				if(oder[i]=="name"){
					cout<<">Name:\n";
					for(int i=0;i<7;++i)
						cout<<'\t'<<show_name[i]<<": "<<name_[i]<<'\n'; 
				}
				else if(oder[i]=="path"){
					cout<<">Path:\n";
					for(int i=0;i<4;++i)
						cout<<'\t'<<show_name[i]<<": "<<path_[i]<<'\n';
					cout<<"\tChecker to program:\t"<<path_[4]<<'\n';
				}
				else if(oder[i]=="need"){
					cout<<">Need:\n";
					for(int i=0;i<3;++i)
					cout<<'\t'<<show_name[i]<<": "<<(need_[i]=='T'?"true\n":"false\n");
					cout<<"\tAutomatic compilation: "<<(auto_compile?"true\n":"false\n");
				}
				else if(oder[i]=="compile"){
					cout<<">Compile:\n";
					cout<<'\t'<<compile<<'\n';
				}
				else cout<<">What is \""+oder[i]+"\" ?\n";
			}
		}else
		if(oder[1]=="change"){
			string tmp1=oder[2],tmp2=oder[3],tmp3=oder[4];
			int x=0;
			
			if(tmp1!="name"&&tmp1!="path"&&tmp1!="need"&&tmp1!="compile"){
				cout<<"<name/path/need/compile>";
				cin>>tmp1; 
			}
			if(tmp1=="compile"){
				tmp2="";
				cout<<"<command>";
				Getline(cin,tmp2);
			}else if(!isNum(tmp2)){
				if(tmp1=="name"){
					for(int i=0;i<7;++i) cout<<'\t'<<i<<": "<<show_name[i]<<'\n';
				}else
				if(tmp1=="path"){
					for(int i=0;i<5;++i) cout<<'\t'<<i<<": "<<show_name[i]<<'\n';
				}else
				if(tmp1=="need"){
					for(int i=0;i<3;++i) cout<<'\t'<<i<<": "<<show_name[i]<<'\n';
					cout<<"\t3: Automatic compilation\n";
				}
				cout<<"<number>";
				while(cin>>tmp2&&!isNum(tmp2)) cout<<"<number>";
			}
			if(tmp3==""&&tmp1!="compile"){
				if(tmp1=="name"){
					cout<<"<file name>";
					cin>>tmp3;
				}else
				if(tmp1=="path"){
					cout<<"<path>";
					cin>>tmp3;
				}else
				if(tmp1=="need"){
					cout<<"<true/false>";
					cin>>tmp3;
				}
			}
			if(tmp1!="compile") x=stoi(tmp2);
			if(tmp1=="name"){
				if(x<7) name_[x]=tmp3;
				else cout<<"Error\n";
			}
			if(tmp1=="path"){
				if(x<5) path_[x]=tmp3;
				else cout<<"Error\n";
			}
			if(tmp1=="need"){
				need_[x]=(tmp3=="true"?'T':'F');
				if(x==3) auto_compile=(tmp3=="true");
			}
			if(tmp1=="compile"){
				compile=tmp2;
			}
		}else
		if(oder[1]=="save"){
			if(oder[2]==""){
				cout<<"<plan name>";
				cin>>oder[2];tot++;
			}
			save_plan(oder[2]);
		}else
		if(oder[1]=="apply"){
			if(oder[2]==""){
				cout<<"<plan name>";
				cin>>oder[2];tot++;
			}
			apply_plan(oder[2]);
		}
		else system(s.c_str());
		nxt:;
		if(s!="") cout<<">>";
	}
	return 0;
}

Leader

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

void color(int c){
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(handle, c);
}
void print(string s,int col){
	color(col);
	cerr<<s;
	color(7);
}

int test_num=10;

bool need_Generator=1,need_Answer=1,need_User=1;

string _name[10],_path[10];

//	_name[0]="Generator",
//	_name[1]="User",
//	_name[2]="Answer",
//	_name[3]="Checker",

//	_name[4]="input.in",
//	_name[5]="output.out",
//	_name[6]="output.ans",
//	
//	_path[0]="program\\generator\\",
//	_path[1]="program\\user\\",
//	_path[2]="program\\answer\\",
//	_path[3]="program\\checker\\",
//	_path[4]="..\\..\\"

ifstream G,A,U,C,cpyin;
ofstream cpyout;

void check(){
	bool f=0;
	G.open(_path[0]+_name[0]+".exe");
	A.open(_path[2]+_name[2]+".exe");
	U.open(_path[1]+_name[1]+".exe");
	C.open(_path[3]+_name[3]+".exe");
	if(!G.is_open()&&need_Generator){
		print("\tCan't find "+_name[0]+".exe",7),f=1;
	}
	if(!A.is_open()&&need_Answer){
		print("\tCan't find "+_name[2]+".exe",7),f=1;
	}
	if(!U.is_open()&&need_User){
		print("\tCan't find "+_name[1]+".exe",7),f=1;
	}
	if(!C.is_open()){
		print("\tCan't find "+_name[3]+".exe",7),f=1;
	}
	if(f) exit(0);
}

void initialize(int argn,char* argv[]){
	need_Generator=(argv[1][0]=='T');
	need_User=(argv[1][1]=='T');
	need_Answer=(argv[1][2]=='T');
	
	_name[0]=argv[2];
	_name[1]=argv[3];
	_name[2]=argv[4];
	_name[3]=argv[5];
	_name[4]=argv[6];
	_name[5]=argv[7];
	_name[6]=argv[8];
	_path[0]=argv[9];
	_path[1]=argv[10];
	_path[2]=argv[11];
	_path[3]=argv[12];
	_path[4]=argv[13];
	
	test_num=atoi(argv[14]); 
}

signed main(int argn,char* argv[]){
	initialize(argn,argv);
	clock_t st,ed;
	int res=-1;

	//检查所需程序是否完全
	check();
	
	for(int test_id=1;test_id<=test_num;++test_id){
		
		//测试点编号 
		cout<<"test "<<test_id<<" :\t\t";
		
		if(need_Generator) system((_path[0]+_name[0]+".exe "+_name[4]).c_str());
		if(need_Answer) system((_path[2]+_name[2]+".exe").c_str());
		
		st=clock();
		if(need_User) res=system((_path[1]+_name[1]+".exe").c_str());
		ed=clock();
		
		if(res&&need_User) print("Runtime Error: Your program returned "+to_string(res)+".\t\t"+to_string(ed-st)+" ms",14);
		else{
			res=system((_path[3]+_name[3]+".exe "+_path[4]+_name[4]+' '+_path[5]+_name[5]+' '+_path[6]+_name[6]).c_str());
			
			if(res>=0) print("\t\t"+to_string(ed-st)+" ms",7);
			
			if(res!=0){
				cpyin.open(_name[4],ios::binary);
				cpyout.open("WA-input\\test "+to_string(test_id)+".in",ios::binary);
				cpyout<<cpyin.rdbuf();
				cpyin.close();
				cpyout.close();
			}
		}
		cout<<'\n';
	}

	return 0;
}

Generator

#include<bits/stdc++.h>
#include<tuple>
#include<vector>
#define uint unsigned int
#define ll long long
#define ull unsigned long long
#define dbl double
#define TIME chrono::system_clock::now().time_since_epoch().count()
using namespace std;
mt19937_64 num(TIME);

template<typename T>inline T INT(T l,T r,char out=0){T x=num()%(r-l+1)+l;if(out)cout<<x<<out;return x;}
template<typename T>inline vector<T> INT(int len,T l,T r,char out=0,char out2=0){vector<T> v(len);for(int i=0;i<len;++i) v[i]=INT(l,r,out);if(out2) cout<<out2;return v;}

template<typename T>inline T FLO(T l,T r,char out=0,int pos=3){
	uniform_real_distribution<long double> flo(l,r);
	T x=flo(num);
	if(out) cout<<fixed<<setprecision(pos)<<x<<out;
	return x;
}
template<typename T>inline vector<T> FLO(int len,T l,T r,char out=0,char out2=0,int pos=3){
	vector<T> v(len);
	for(int i=0;i<len;++i) v[i]=FLO(l,r,out,pos);
	if(out2) cout<<out2;
	return v;
}

inline char CH(char l,char r,char out=0){char x=num()%(r-l+1)+l;if(out)cout<<x<<out;return x;}
inline char CH(string s,char out=0){char x=s[INT(0,(int)s.size()-1)];if(out)cout<<x<<out;return x;}
inline string STR(int len,char l,char r,char out=0,char out2=0){string s;for(int i=1;i<=len;++i) s+=CH(l,r,out);if(out2) cout<<out2;return s;}

template<typename T> inline T Pick(initializer_list<T> s,char out=0){
	T x=*(s.begin()+num()%s.size());
	if(out) cout<<x<<out;
	return x;
}
template<typename T>inline vector<T> Pick(int len,initializer_list<T> s,char out=0,char out2=0){
	vector<T> v(len);
	for(int i=0;i<len;++i) v[i]=Pick(s,out);
	if(out2) cout<<out2;
	return v;
}

pair<int,int> ITV(int l,int r,char out=0){
	int x=INT(l,r),y=INT(l,r);
	if(x>y) swap(x,y);
	if(out) cout<<x<<' '<<y<<out;
	return {x,y};
}

auto Graph(int point,int edge,int weightl=0,int weightr=0,vector<string> t={}){
	map<string,bool> type;
	for(string s:t) type[s]=1;
	bool repeat=type["repeat"],directed=type["directed"],
	forest=type["forest"],self=type["self"],
	heap=type["max-heap"]|type["min-heap"]|type["heap"];
	vector<tuple<int,int,int> > g;
	map<pair<int,int>,bool> vis;
	vector<int> tmp;
	if(type["max-heap"]) for(int i=point;i>=1;--i) tmp.emplace_back(i);
    else for(int i=1;i<=point;++i) tmp.emplace_back(i);
	if(!heap) shuffle(tmp.begin(),tmp.end(),num);
	if(!forest)
    for(int i=1,x,y;i<(int)tmp.size();++i){
        x=tmp[INT(0,i-1)],y=tmp[i];
        if(!repeat){
			if(directed)vis[{x,y}]=1;
			else vis[{x,y}]=vis[{y,x}]=1;
		}
		g.emplace_back((tuple<int,int,int>){x,y,INT(weightl,weightr)});
    }
	if(!forest) edge-=point-1;
	if(!type["tree"])
	while(edge>0){
		int x=INT(1,point),y=INT(1,point);
		while(vis[{x,y}]||(x==y&&!self)) x=INT(1,point),y=INT(1,point);
		if(!repeat){
			if(directed)vis[{x,y}]=1;
			else vis[{x,y}]=vis[{y,x}]=1;
		}
		g.emplace_back((tuple<int,int,int>){x,y,INT(weightl,weightr)});
		edge--;
	}
	if(type["value"]) for(auto x:g)cout<<get<0>(x)<<' '<<get<1>(x)<<' '<<get<2>(x)<<'\n';
	else if(type["out"]) for(auto x:g)cout<<get<0>(x)<<' '<<get<1>(x)<<'\n';
	return g;
}

void Generate(){
	//write here!!!!!!!!!!!!!!!! 
	
}

signed main(int argn,char* argv[]){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	if(argn==2) freopen(argv[1],"w",stdout);
	Generate();
	return 0;
}

Checker

#include<bits/stdc++.h>
#include<windows.h>
using namespace std;
ifstream ain,uin;

/*
return 0: Accepted
return 1: Wrong answer: Objective wrong answer
return 2: Wrong answer: Output longer than answer
return 3: Wrong answer: Output shorter than answer
return -1: System error: can't find corrent.out
return -2: System error: can't find tested.out
else System error: Unknown Error 
*/

void color(int c){
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(handle, c);
}
void print(string s,int col){
	color(col);
	cerr<<s;
	color(7);
}

string user,answer,input;

int Judge(){
	//Write Special Judge here
	string s1,s2;
	bool f=1;
	while(ain>>s1&&uin>>s2){
		if(s1!=s2) f=0;s1="",s2="";
	}
	ain>>s1;uin>>s2;
	if(s1==""&&s2!="") return 2;
	if(s2==""&&s1!="") return 3;
	if(f) return 0;
	else return 1;
} 

signed main(int argn,char* argv[]){
	
	input=argv[1];
	user=argv[2];
	answer=argv[3];
	
	ios::sync_with_stdio(0);
	ain.tie(0),uin.tie(0);
	ain.open(answer);
	uin.open(user);
	
	if(!ain.is_open()) return -1;
	if(!uin.is_open()) return -2;
	
	int res=Judge();
	
	if(res==0){
		print("Accepted!",10);
	}else
	if(res==1){
		print("Wrong answer: Objective wrong answer",4);
	}else
	if(res==2){
		print("Wrong answer: Output longer than answer",4);
	}else
	if(res==3){
		print("Wrong answer: Output shorter than answer",4);
	}else
	if(res==-1){
		print("System error: can't find "+answer,13);
	}else
	if(res==-2){
		print("System error: can't find "+user,13);
	}else{
		print("System error: Unknown Error",13);
	}
	
	return res;
}

更新日志

  • 2026/7/25 16:05 略微降低了生成树的空间开销。
  • 2026/7/25 16:39 Graph函数更新了heap、min-heap、max-heap命令。更新了排版。
  • 2026/7/25 20:51 加入了答案比较器、对拍启动器、正确程序头与待测程序头,至此,完整对拍程序已经完工。
  • 2026/7/26 10:39 更新1.1测试版,加入计时功能。
  • 2026/7/26 10:48 将此文章同步与洛谷。
  • 2026/7/26 19:14 更新1.1.1正式版优化了Special Judge的书写难度,新增了RE、UKE报错。
  • 2026/7/26 20:19 修复了一些BUG。由于不同编译器对中文注释的处理不同,将中文注释改为了英文注释,并优化了文件的大小。
  • 2026/7/27~2026/7/31 陆续发布了1.1.2(测试)、1.1.3(正式)、1.1.4(正式)
  • 不知道什么时候 更新了1.1.5、1.2.0
  • 2026/8/18: 发布了2.0(测试)
  • 2026/8/21: 发布了2.0(用户版)、2.0(开源),更新了文章排版。

更新内容:

2.0:

大更新!!!!
内容较多。

1.2.0:

  • 加入测试性加入指令。

1.1.5:

  • 测试性加入随机排列。

1.1.4(正式):

  • 加入了Warning报错。
  • 正式加入报错信息说明。
  • 优化了Special Judge的书写环境。
  • 优化了文章排版。

1.1.3(正式):

  • 修复了1.1.2模板函数的锅。
  • 更改了「随机样例生成器」的生成随机数函数。
  • 加入了随机浮点数的生成。
  • 从原函数分离出Pick()函数。

1.1.2(测试):

  • 尝试加入报错信息说明。
  • 使用模板函数合并相似函数(也出了巨大的锅)。

1.1.1(正式):

  • 优化了Special Judge书写。
  • 新增RE、UKE报错。

1.1(测试):

  • 加入计时功能。

1.0 :

  • 完整对拍程序,可以完成对拍。

通知

3.0版本正在加紧制作中
是的没错这作者又开始代码重构了

posted @ 2026-07-25 08:22  LZYXT  阅读(73)  评论(9)    收藏  举报