CarYon 工作原理 - luosiwei-cmd/CarYon GitHub Wiki

CarYon 工作原理

需要了解 CarYon 的工作原理,才可以更好地使用 CarYon。

注意,在阅读本文之前,您需要阅读所有 Wiki 并且已经使用 CarYon 造过几组数据,这样您才能了解 CarYon 真正的实现细节。

认真读完本文后,您可以选择在光荣榜留名。

大体流程

普通数据生成

我们从一个最简单的 test.cpp 开始讲起。

下面是一个生成 A+B Problem 的 test.cpp

//a+b problem test
#include"caryon.h"
using namespace std;
using namespace ca;
int main(){
	dataname="A+B_Problem_Test";
	makein(1,10)/*make 10 in files*/{
		csh();
		inint(cyrand(0,100));
		instring("  ");
		inint(cyrand(0,100));
	}
	makeout(1,10);
	closefile();
	return 0;
}

头文件和命名空间不用讲。先来讲讲 dataname,即前缀的实现。

datanamecaryon.h 的定义是 std::string dataname,剩下的就在 test.cpp 中供使用者填写。

首先,我们得先了解 CarYon 最基本的工作原理。

CarYon 最基本的工作原理就是文件操作。其过程是建立文件,并将用户设定写入文件的东西写入文件。

那么输出只需要运行 test.exe 将生成的输入文件输入,并获得输出,将结果写入对应的文件就可以了。

所有生成的测试样例会被放在 data-dataname 中,所有 in 文件等等格式是 datanameno.in,即dataname+序号.inout文件同理。

dataname 就是在 CarYon 建立文件夹和文件的时候,在写入那个freopen命令的名称的前缀。

具体请看整个 namespace inout 的源码。请见下文。

然后我们来看 makein(start,end){},这个具体的实现非常简单,就是一个循环,为了用户。下面展示这个东西的宏定义:

#define makein(m, n) for (ci = m; ci <= n; ci++)

ci是序号。因此,在使用 CarYon 的时候,请避免在 makein 中定义变量 ci

循环就是依次执行制作文件。

下面来看 csh();

这个函数必须包含在这里,为什么呢?我们先来看定义:

void csh() {
    cnt = 0;
}

就这?cnt=0?这里涉及着一些不可告人的秘密qwq。

下面makeout 的原理上文已经讲过。

closefile() 就是很简单地重定向到控制台。

上面我们就分析完了test.cpp必备的几项技能。CarYon 的数据生成也就是这个原理。

程序对拍功能

程序的对拍全部集中在namespace cydebug中,大体可以分为三个部分:

  1. 制作对拍文件

  2. 比较用户输出和标准输出

  3. 返回结果,输出日志

制作对拍文件也就是 myprogrm.exe 对应制作的输入文件其输出的文件,保存为 debug-dataname文件夹,每个文件类型为 dataname+序号+.ans。但是这里和传统的数据生成还有一点不同。这里还记录了程序对应的运行时间,储存在 std::stringstream sp 中;

然后是比较,这里写了三个比较器,三个比较器的不同请参阅其他 Wiki。下面给出三个比较器的源码供参考:

FULLTest:

#include<bits/stdc++.h>
#include<ctime>
using namespace std;
#define UKE -1
#define AC 1
#define WA 0
int compareFile(FILE* file_compared, FILE* file_checked){
    bool diff = 0;
    int N = 65536;
    char* b1 = (char*) calloc (1, N+1);
    char* b2 = (char*) calloc (1, N+1);
    size_t s1, s2;

    do {
        s1= fread(b1,1, N, file_compared);
        s2 = fread(b2,1, N, file_checked);
        if ((s1!=s2)||memcmp(b1, b2, s1)) {
            diff = 1;
            break;
        }
    }while(!feof(file_compared)||!feof(file_checked));

    free(b1);
    free(b2);

    if (diff) return 0;
    else return 1;
}
int main(int argc,char* argv[]){
	if(argc<=2){
		return UKE;
	}
	FILE* fuser=fopen(argv[1],"r");
	FILE* fstd=fopen(argv[2],"r");
	if(compareFile(fuser,fstd)==1){
		return AC;
	}
	else {
		return WA;
	}
	return 0;
} 

NOIPStyle:

#include <bits/stdc++.h>
using namespace std;
#define UKE -1
#define AC 1
#define WA 0
int compareFile(FILE* file_compared, FILE* file_checked) {
    bool   diff = 0;
    int    N    = 65536;
    char   b1[65536], b2[65536];
    size_t s1, s2;
    while (1) {
        if (fgets(b1, N, file_compared) == NULL ||
            fgets(b2, N, file_checked) == NULL) {
            break;
        }
        s1 = strlen(b1);
        s2 = strlen(b2);
        if ((s1 != s2 && s1 + 2 != s2 && s1 - 2 != s2 && s1 + 1 != s2 &&
             s1 - 1 != s2) ||
            memcmp(b1, b2, min(s1, s2) - 1)) {
            diff = 1;
            break;
        }
    }
    free(b1);
    free(b2);
    if (diff)
        return 0;
    else
        return 1;
}
int main(int argc, char** argv) {
    if (argc < 2) {
        return UKE;
    }
    FILE* fuser = fopen(argv[1], "r");
    FILE* fstd  = fopen(argv[2], "r");
    if (compareFile(fuser, fstd) == 1) {
        return AC;
    }
    else {
        return WA;
    }
    return 0;
}

IOIStyle:

#include<bits/stdc++.h>
using namespace std;
#define UKE -1
#define AC 1
#define WA 0
int cnt=1;
int compareFile(FILE* file_compared, FILE* file_checked){
    bool diff=0;
    int N=65536;
    char b1[N],b2[N];
    size_t s1,s2;
    while(1){
    	cnt++;
		if(fgets(b1,N,file_compared)==NULL||fgets(b2,N,file_checked)==NULL){
			break;
		}  
        s1=strlen(b1);
        s2=strlen(b2);
        if((s1!=s2&&s1+2!=s2&&s1-2!=s2&&s1+1!=s2&&s1-1!=s2)||memcmp(b1,b2,min(s1,s2)-1)){
            cerr<<"Wrong Answer On Row "<<cnt-1<<", expected "<<b1<<", found "<<b2;
			diff=1;
            break;
        }
    }
    free(b1);
    free(b2);
    if(diff)
		return 0;
    else 
		return 1;
}
int main(int argc,char* argv[]){
	if(argc<=2){
		return UKE;
	}
	FILE* fuser=fopen(argv[1],"r");
	FILE* fstd=fopen(argv[2],"r");
	system("mkdir IOI");
	freopen("IOI./IOI.log","w",stderr);
	if(compareFile(fuser,fstd)==1){
		cerr<<"Accept.\n";
		return AC;
	}
	else {
		return WA;
	}
	return 0;
} 

比较文件就是要针对每一个文件,先判断其是否超出运行时间,直接输出 TLE,反之,利用比较器的返回值判断 WA 或 AC。

于是就是下面这段经典代码:

std::string command = "tools\\Compare\\NOIPStyle.exe debug-" +
                              dataname + "\\" + dataname + Debug1 +
                              ".ans data-" + dataname + "\\" + dataname +
                              Debug1 + ".out";
        int flag = system(command.c_str());
        sp >> runtime;
        freopen("Debug.log", "a", stdout);
        if (runtime > maxtime) {
            std::cout << "TestCase " << i
                      << ", result: TLE. The program\'s runtime is " << runtime
                      << " ms.\n";
        }
        else if (flag == 1) {
            std::cout << "TestCase " << i << ", result: AC.\n";
        }
        else if (flag == 0) {
            std::cout << "TestCase " << i << ", result: WA.\n";
        }
        else {
            std::cout << "TestCase " << i << ", result: UKE.\n";
        }

这是整个比较的核心。

然后是写入日志,也在上面的源码里面了。

仅编写配置文件生成数据

这一段的实现主要是编写一个解释器,用来解释对应的配置文件从而生成 test.cpp。其可以分为三个领域。

生成

对应每一行生成一行 test.cpp。具体的实现请看之后给出的源码。

报错

当检测到 CHECKER 返回的信息异常或者处理异常的时候,会报错并渲染失败。

CHECKER

检查 test.cpp 的格式和变量名,分支,循环是否正常。

下面给出渲染器的源码:

首先是头文件:

#ifndef ANALYSIS_HPP 
#define ANALYSIS_HPP 
#include<bits/stdc++.h>
#include<io.h>
#include<windows.h>
using namespace std;
struct _finddata_t info;
ofstream fout("test.cpp");
std::string type;
int start_d,end_d;
int CNT,_CNT,if_cnt,for_cnt,tab_cnt;
string _variable[10000]={""};
int _i=0;
string maketab(){
	clog<<"[CHECKER] Checking how many space(s) will be used.\n";
	string temp;
	temp="        ";
	tab_cnt=if_cnt+for_cnt;
	int i;
	for(i=0;i<tab_cnt;i++){
		temp+="    "; 
	}
	clog<<"[CHECKER] For row "<<CNT<<", there will be "<<i*4+8<<" space(s) here.\n";
	return temp;
}
void init(){
	fout<<"#include\"caryon.h\"\n";
	fout<<"using namespace std;\n";
	fout<<"using namespace ca;\n";
	fout<<"\n";
	fout<<"int main(){\n";
}
void end(){ 
	fout<<"    }\n";
	fout<<"    makeout("<<start_d<<","<<end_d<<");\n";
	fout<<"    return 0;\n";
	fout<<"}\n";
	cout<<"Analysis end with succeed.\n\n";
	cout<<"Please check the analysis.log for more information.\n";
	system("pause");
}
void addMakein(int a,int b){
	fout<<"    makein("<<a<<","<<b<<"){\n";
	fout<<"        csh();\n";
	clog<<"[LOG] Makein function was written successfully.\n";
}
void addInint(int a,int b){
	fout<<maketab()<<"inint(cyrand("<<a<<","<<b<<"));\n";
	clog<<"[LOG] Make a random number successfully.\n";
}
void addInint(string a){
	fout<<maketab()<<"inint("<<a<<");\n";
	clog<<"[LOG] Make a number successfully.\n";
}
void addInstring(string a){
	fout<<maketab()<<"instring(\""<<a<<"\");\n";
	clog<<"[LOG] Make a string or a space successfully.\n";
}
void addInstring(int a){
	fout<<maketab()<<"instring(cyrand_word("<<a<<"));\n";
	clog<<"[LOG] Make a random string successfully.\n";
}
void makedataERR(){
	cerr<<"[ERR] on row "<<CNT<<", more than 1 makedata operation is not be allowed. | The makedata operation may be not in the fitst row. Plese check.\n";
	fout<<"\n\n//Analysis failed, plese check stderr to know more.\n";
	cout<<"Analysis failed. Please check the analysis.log for more information.\n";
	system("pause");
	exit(0);
}
void NothatERR(){
	cerr<<"[ERR] on row "<<CNT<<", unknown operation found.\n";
	fout<<"\n\n//Analysis failed, plese check stderr to know more.\n";
	cout<<"Analysis failed. Please check the analysis.log for more information.\n";
	system("pause");
	exit(0);
}
void NoMakedataERR(){
	cerr<<"[ERR] there is not a makedata opertion in your compile file.\n";
	fout<<"\n\n//Analysis failed, plese check stderr to know more.\n";
	cout<<"Analysis failed. Please check the analysis.log for more information.\n";
	system("pause");
	exit(0);
}
void NoiniERR(){
	cerr<<"[ERR] cannot find file: control.ini.\n";
	fout<<"\n\n//Analysis failed, plese check stderr to know more.\n";
	cout<<"Analysis failed. Please check the analysis.log for more information.\n";
	system("pause");
	exit(0);  
}
void variWrongERR(){
	cerr<<"[ERR] on row "<<CNT<<", the variable name is wrong.\n";
	fout<<"\n\n//Analysis failed, plese check stderr to know more.\n";
	cout<<"Analysis failed. Please check the analysis.log for more information.\n";
	system("pause");
	exit(0);
}
void twoVariERR(){
	cerr<<"ERR: on row "<<CNT<<", the variable name has already been named.\n";
	fout<<"\n\n//Analysis failed, plese check stderr to know more.\n";
	cout<<"Analysis failed. Please check the analysis.log for more information.\n";
	system("pause");
	exit(0);
}
void nothisVariERR(){
	cerr<<"[ERR] on row "<<CNT<<", there is no variable name "<<type<<".\n";
	fout<<"\n\n//Analysis failed, plese check stderr to know more.\n";
	cout<<"Analysis failed. Please check the analysis.log for more information.\n";
	system("pause");
	exit(0);
}
void NoForEndERR(){
	cerr<<"[ERR] The for do not have an end.";
	fout<<"\n\n//Analysis failed, plese check stderr to know more.\n";
	cout<<"Analysis failed. Please check the analysis.log for more information.\n";
	system("pause");
	exit(0);
}
void addInt(string type){
	fout<<maketab()<<"int "<<type<<";\n";
	clog<<"[LOG] Add int variable "<<type<<" successfully.\n";
	_variable[_i++]=type;
}
void addIntAssign(string type,int a){
	fout<<maketab()<<type<<"="<<a<<";\n";
	clog<<"[LOG] Assign variable "<<type<<" to "<<a<<" successfully.\n";
}
bool isvari(string type){
	clog<<"[CHECKER] Checking if "<<type<<" is a variable name.\n";
	if(!((type[0]>='a' and type[0]<='z')or(type[0]>='A' and type[0]<='Z')or(type[0]=='_')or(type[0]=='$'))){
		return false;
	}
	for(int i=1;i<type.size();i++){
		if(!((type[i]>='a' and type[i]<='z')or(type[i]>='A' and type[i]<='Z')or(type[i]=='_')or(type[i]=='$')or(type[i]>='0' and type[i]<='9'))){
			clog<<"[CHECKER] "<<type<<" is not a variable name.\n";
			return false;   
		}
	}
	clog<<"[CHECKER] "<<type<<" is a variable name. Accept.\n";
	return true;
}
bool alreadyhave(string type){
	clog<<"[CHECKER] Checking if variable "<<type<<" has already used.\n";
	for(int i=0;i<_i;i++){
		if(_variable[i]==type){
			clog<<"[CHECKER] Variable "<<type<<" has already used.\n";
			return false;
		}
	}
	clog<<"[CHECKER] Variable "<<type<<" has not been used yet.\n";
	return true;
}
void addvariInint(string type){
	fout<<maketab()<<"inint("<<type<<");\n";
	clog<<"[LOG] Make a variable number successfully.\n";
}
void assignrandvari(int start,int end,string type){
	fout<<maketab()<<type<<"=cyrand("<<start<<","<<end<<");\n";
	clog<<"[LOG] Assign  variable "<<type<<" with a random number successfully.\n";
}
void addFor(string i,int start,int end,int add){
	fout<<maketab()<<"for("<<i<<"="<<start<<";"<<i<<"<="<<end<<";"<<i<<"+="<<add<<"){\n";
	clog<<"[LOG] Add a for successfully.\n";
	for_cnt++;
}
void endFor(){
	for_cnt--;
	fout<<maketab()<<"}\n";
	clog<<"[LOG] End a for successfully.\n";
}
void NotinForERR(){
	cerr<<"[ERR] On row "<<CNT<<", the continue/break/sf is not in a for.\n";
	fout<<"\n\n//Analysis failed, plese check stderr to know more.\n";
	cout<<"Analysis failed. Please check the analysis.log for more information.\n";
	system("pause");
	exit(0);
}
void NotinIfERR(){
	cerr<<"[ERR] On row "<<CNT<<", the fi is not in an if.\n";
	fout<<"\n\n//Analysis failed, plese check stderr to know more.\n";
	cout<<"Analysis failed. Please check the analysis.log for more information.\n";
	system("pause");
	exit(0);
}
void NoIfEndERR(){
	cerr<<"[ERR] A/Some if(s) do not have an end.";
	fout<<"\n\n//Analysis failed, plese check stderr to know more.\n";
	cout<<"Analysis failed. Please check the analysis.log for more information.\n";
	system("pause");
	exit(0);
}
void addContinue(){
	fout<<maketab()<<"continue;\n";
	clog<<"[LOG] Add a \"continue\" successfully.\n";
}
void addBreak(){
	fout<<maketab()<<"break;\n";
	clog<<"[LOG] Add a break successfully.\n";
}
void addIf(string type){
	fout<<maketab()<<"if("<<type<<"){\n";
	clog<<"[LOG] Add an if successfully.\n";
	if_cnt++;
}
void endIf(){
	if_cnt--;
	fout<<maketab()<<"}\n";
	clog<<"[LOG] End an if successfully.\n";
}
void addForWithVariEnd(string a,int b,string c,int d){
	fout<<maketab()<<"for("<<a<<"="<<b<<";"<<a<<"<="<<c<<";"<<a<<"+="<<d<<"){\n";
	clog<<"[LOG] Add a for with a variable end successfully.\n";
	for_cnt++;
}
bool endForc(){
	clog<<"[CHECKER] Checking if sf/continue/break is in a fs.\n";
	if(for_cnt){
		clog<<"[CHECKER] Sf/continue/break is in a fs.\n";
		return true;
	}
	else{
		clog<<"[CHECKER] Sf/continue/break is not in a fs.\n";
		return false;
	}
}
bool endIfc(){
	clog<<"[CHECKER] Checking if fi is in an if.\n";
	if(if_cnt){
		clog<<"[CHECKER] Fi is in an if.\n";
		return true;
	}
	else{
		clog<<"[CHECKER] Fi is not in an if.\n";
		return false;
	}
}
#endif //#ifndef ANALYSIS_HPP 
/*ANALYSIS.HPP*/ 

然后是源文件:

#include "analysis.hpp"
using namespace std;
int main() {
    freopen("analysis.log", "w", stderr);
    init();
    if (_findfirst("control.ini", &info) == -1) {
        NoiniERR();
    }
    ifstream fin("control.ini");
    while (fin >> type) {
        CNT++;
        if (type == "makedata") {
            _CNT++;
            if (CNT != 1) {
                makedataERR();
            }
            fin >> start_d >> end_d;
            addMakein(start_d, end_d);
        }
        else if (type == "inint") {
            fin >> type;
            if (type == "cyrand") {
                int start, end;
                fin >> start >> end;
                addInint(start, end);
            }
            else if (type == "variable") {
                fin >> type;
                if (!alreadyhave(type)) {
                    addvariInint(type);
                }
                else {
                    nothisVariERR();
                }
            }
            else {
                addInint(type);
            }
        }
        else if (type == "instring") {
            fin >> type;
            if (type != "cyrand")
                addInstring(type);
            else {
                int a;
                fin >> a;
                addInstring(a);
            }
        }
        else if (type == "space") {
            addInstring(" ");
        }
        else if (type == "int") {
            fin >> type;
            if (isvari(type)) {
                if (alreadyhave(type))
                    addInt(type);
                else
                    twoVariERR();
            }
            else {
                variWrongERR();
            }
        }
        else if (type == "assignment") {
            fin >> type;
            int _a;
            fin >> _a;
            if (!alreadyhave(type)) {
                addIntAssign(type, _a);
            }
            else {
                nothisVariERR();
            }
        }
        else if (type == "variable_cyrand") {
            fin >> type;
            int start, end;
            fin >> start >> end;
            if (alreadyhave(type)) {
                nothisVariERR();
            }
            else {
                assignrandvari(start, end, type);
            }
        }
        else if (type == "fs") {
            string __i;
            fin >> __i;
            int ___start, ___end, ___add;
            fin >> ___start >> ___end >> ___add;
            if (!alreadyhave(__i))
                addFor(__i, ___start, ___end, ___add);
            else {
                type = __i;
                nothisVariERR();
            }
        }
        else if (type == "fs_end_withvari") {
            string __i, __j;
            fin >> __i;
            int ___start, ___add;
            fin >> ___start >> __j >> ___add;
            if (alreadyhave(__i) || alreadyhave(__j)) {
                if (alreadyhave(__i)) {
                    type = __i;
                    nothisVariERR();
                }
                else {
                    type = __j;
                    nothisVariERR();
                }
            }
            else {
                addForWithVariEnd(__i, ___start, __j, ___add);
            }
        }
        else if (type == "sf") {
            if (endForc())
                endFor();
            else
                NotinForERR();
        }
        else if (type == "continue") {
            if (endForc()) {
                addContinue();
            }
            else {
                NotinForERR();
            }
        }
        else if (type == "break") {
            if (endForc()) {
                addBreak();
            }
            else {
                NotinForERR();
            }
        }
        else if (type == "if") {
            fin >> type;
            addIf(type);
        }
        else if (type == "fi") {
            if (endIfc())
                endIf();
            else
                NotinIfERR();
        }
        else {
            NothatERR();
        }
    }
    if (_CNT == 0) {
        NoMakedataERR();
    }
    if (for_cnt) {
        NoForEndERR();
    }
    if (if_cnt) {
        NoIfEndERR();
    }
    end();
}

这些都是核心。

功能分布

所有集中的功能都放在一个命名空间里。最终用户使用的 namespace ca 是包含了所有命名空间的集合。您也可以利用单独的命名空间使用具体的函数。这在老版的编译器中会降低执行时间。但是新版编译器并不会

下面给出 namespace ca 的定义:

namespace ca {
using namespace crand;
using namespace cmath;
using namespace inout;
using namespace cydebug;
using namespace cconst;
using namespace cgraph;
#if __cplusplus >= 201103L
using namespace caryon_cpp11;
#endif  //#if __cplusplus>=201103
using namespace cgeo;
}  // namespace ca

这里有很多命名空间,我们一个一个讲。

源码剖析

namespace crand

这个命名空间包含着 CarYon 的随机数库。

几乎所有和随机有关的 CarYon 内置函数都在此定义。

下面给出源码:

namespace crand {
bool isInit;
int  MTindex;
ll   MT[624];
void csrand(int seed) {
    MTindex = 0;
    isInit  = 1;
    MT[0]   = seed;
    for (int i = 1; i < 624; i++) {
        int t = 1812433253 * (MT[i - 1] ^ (MT[i - 1] >> 30)) + i;
        MT[i] = t & 0xffffffff;
    }
}
inline void generate() {
    for (int i = 0; i < 624; i++) {
        long long y = (MT[i] & 0x80000000) + (MT[(i + 1) % 624] & 0x7fffffff);
        MT[i]       = MT[(i + 397) % 624] ^ (y >> 1);
        if (y % 2 == 1)
            MT[i] ^= 2147483647;
    }
}
inline int cyrand() {
    if (!isInit)
        csrand((int)time(NULL));
    if (MTindex == 0)
        generate();
    int y   = MT[MTindex];
    y       = y ^ (y >> 11);
    y       = y ^ ((y << 7) & 1636928640);
    y       = y ^ ((y << 15) & 1022730752);
    y       = y ^ (y >> 18);
    MTindex = (MTindex + 1) % 624;
    return y;
}
inline ll cyrand_ll() {
    return ((ll)(cyrand()) << 31) + cyrand();
}
inline int cyrand(int a, int b) {
    if (a > b)
        a = b;
    if (a == b)
        return a;
    else
        return cyrand() % (b - a + 1) + a;
}
inline ll cyrand_ll(ll a, ll b) {
    if (a > b)
        a = b;
    if (a == b)
        return a;
    else
        return cyrand_ll() % (b - a + 1) + a;
}
inline bool cyrand_bool() {
    if (cyrand(0, 1) == 0)
        return false;
    else
        return true;
}
inline char cyrand_letter() {
    return cyrand(32, 126);
}
inline char cyrand_engs() {
    return 'a' + cyrand(0, 26);
}
inline char cyrand_engb() {
    return 'A' + cyrand(0, 26);
}
inline char cyrand_fomatc() {
    switch (cyrand(0, 4)) {
        case 0: {
            return '\n';
            break;
        }
        case 1: {
            return '\t';
            break;
        }
        case 2: {
            return '\r';
            break;
        }
        case 3: {
            return '\v';
            break;
        }
        case 4: {
            return '\f';
            break;
        }
    }
}
inline std::string cyrand_word(int a) {
    std::string chen_zhe;
    for (int kkksc03 = 0; kkksc03 < a; kkksc03++) {
        if (cyrand_bool()) {
            chen_zhe[kkksc03] = cyrand_engs();
        }
        else {
            chen_zhe[kkksc03] = cyrand_engb();
        }
    }
    return chen_zhe;
}
inline std::string cyrand_article(int a) {
    std::string soha;
    soha = cyrand_word(cyrand(1, 10));
    for (int lzn = 1; lzn < a; lzn++) {
        soha = soha + " " + cyrand_word(cyrand(1, 10));
    }
    return soha;
}
template < typename T >
inline T choice(T* a, int lbound, int ubound) {
    return a[cyrand(lbound, ubound)];
}
inline double doubleRandom() {
    srand(time(0));
    return (double)(rand() / (double)RAND_MAX);
}
inline bool __checktmp(int* arr, int tmp, int flag, int end) {
    if (flag == 0) {
        return true;
    }
    for (int i = 0; i < end; i++) {
        if (flag == -1) {
            if (arr[i] == tmp) {
                return false;
            }
        }
        else if (flag == 1) {
            if (arr[i] > tmp) {
                return false;
            }
        }
        else if (flag == 2) {
            if (arr[i] < tmp) {
                return false;
            }
        }
        else if (flag == 3) {
            if (arr[i] >= tmp) {
                return false;
            }
        }
        else if (flag == 4) {
            if (arr[i] <= tmp) {
                return false;
            }
        }
    }
    return true;
}
inline void randomArr(int* arr, int n, int lower, int upper, int flag) {
    for (int i = 0; i < n;) {
        int tmp = cyrand(lower, upper);
        if (__checktmp(arr, tmp, flag, i - 1)) {
            arr[i++] = tmp;
        }
    }
}
}  // namespace crand

函数的功能都可以通过一些 Wiki 查看。

其中有几个特殊的函数是内部函数,并没有在 Wiki 中提出。如果您有更好的实现这些函数的方法,欢迎进行 Pull Request。

其中还有一个工具函数:

template < typename T >
inline T choice(T* a, int lbound, int ubound) {
    return a[cyrand(lbound, ubound)];
}

请查看 工具函数 Wiki 了解该功能的使用。

这些随机的东西是您生成数据的重要组成部分。

namespace cmathnamespace cgeo

数学库和几何库,不解释。

namespace inoutnamespace cydebug

负责最重要的组成部分。分别是生成文件和程序对拍。instring,inint,in,makeout,debug等函数都内含于此。

namespace cconst

负责常用常量。

namespace cgraph

随机树和随机图。

namespace caryon_cpp11

C++11 的 CarYon 特别支持。源码如下:

#if __cplusplus >= 201103L
namespace caryon_cpp11 {
template < typename T >
T choice_plus(std::initializer_list< T > a) {
    std::vector< T > b;
    for (auto i : a) {
        b.push_back(i);
    }
    return b[crand::cyrand(1, b.size()) - 1];
}
}  // namespace caryon_cpp11
#endif  //#if __cplusplus>=201103

内含一个工具函数choice_plus({0,1,...,2,4})

了解了 CarYon 的工作原理后,您可以自由地使用 CarYon 了。不再受任何文档的拘束!您甚至可以在光荣榜留名。

⚠️ **GitHub.com Fallback** ⚠️