Skip to content

Latest commit

 

History

History
159 lines (120 loc) · 6.45 KB

README.md

File metadata and controls

159 lines (120 loc) · 6.45 KB

Judger

一个用来对拍和生成随机数据的程序(Windows平台)。

A tool for OIer to generate random input and compare the result of two programs (in Windows).

构建

这个项目是用Visual Studio 2017写的,所以克隆这个项目用Visual Studio打开Judger.sln,按生成解决方案即可。

快速开始对拍

确保你的文件夹中有

  • 你要对拍的程序
  • 正确的程序(建议:把正确的程序命名为带force或者ac的名字,这样Judger.exe更容易识别出要对拍的程序。)
  • 生成数据的程序

将Judger.exe放到你要对拍的程序的目录下,运行Judger.exe,按空格使用生成向导,然后按照向导的提示输入即可。

产生正确的JudgeInfo.txt后,再次运行Judger.exe即可开始对拍。

对拍时可以按p键暂停,按Alt+J最小/最大化。当处于最小化时拍出错误或发生异常,Judger会自动弹出。

注意,每次修改JudgeInfo.txt后,请重新运行Judger.exe。


Judger的数据生成语言

这个语言用于快速、便捷地生成随机数据,从而不用专门去写一个生成数据的程序。当然,这套简单的语言并不能产生有特殊要求的数据,这时候还是只能专门写一个生成数据的程序。

首先,这个部分请写在input:下。

直接输出

这个语言很简单,你输入的大部分字符都是直接输出的。比如你的input部分如下:

input:
// I am notes.
I want this string.\n
But you don't 
want this string.

那么你的输入文件就会得到:

I want this string.
But you don't want this string.

正如你所见,输出换行用的是'\n',而在input:中换行并没有什么用处。实际上,Judger在处理这段语言时会把所有行拼接到一行中,所以你可以随心所欲的换行而不会影响输出。

input:里你也可以写注释,不过请确保//在行首。

当然,有些字符是不可以(或者不建议)直接输出的,比如'(',')','[',']','{','}',';',这时候你需要在它们之前加一个反斜杠'\'来输出它们。

变量

这个语言只支持以一个英文字母命名的变量,区分大小写,共52个。

使用变量的基本形式是x(expr1)x(expr1, expr2)(变量与左括号之间不能有空格,否则会被Judger视为普通字符直接输出),其中x是变量名,expr1和expr2是表达式,表达式中可以含有变量(详见表达式小节)。前一种形式是将expr1的值赋给x,后一种形式是随机产生一个在[expr1, expr2](或[expr2, expr1],视两个表达式的结果大小而定)的整数赋给x。未初始化的变量值未知

正常情况下,变量是默认输出的。你也可以用x()直接输出变量x的值而不进行赋值。如果你有变量不想输出,可以在变量与左括号之间插入'$',即x$(expr1)x$(expr1, expr2)

注意:变量小写字母c是特殊的、专门用来输出字符的变量,其输出的是变量值对应的ASCII码表中的字符。

表达式

在这个语言的表达式中,运算数可以是数字(范围在long long以内),变量和字符常量(比如'a',等价于输入了数字97)。

运算符有以下9种,都是二元运算符:

  1. a+b:返回a与b的和
  2. a-b:返回a与b的差
  3. a*b:返回a与b的积
  4. a/b:返回a与b的商(整数除法)
  5. a<b:返回a与b的较小值
  6. a>b:返回a与b的较大值
  7. a^b:返回a的b次方
  8. a%b:返回a模b
  9. a=b:若a与b相等则返回1,否则返回0

运算符的优先级(编号越小优先级越高):

  1. '(',')'
  2. '^'
  3. '*','/','%'
  4. '+','-'
  5. '<','>'
  6. '='

运算时同优先级的运算符采用左结合的方式。

循环语句

循环语句有三种用法:

  1. [expr]body;,其中expr是表达式,其值代表循环的次数,body是循环体,最后用分号结束。
  2. [expr,varible]body;,其中varible是变量名,这样写声明了varible是循环变量,它从1开始,每次循环结束后+1。你可以在循环体内部任意的改动varible的值,这不会影响循环的次数。其余同1。
  3. [expr,varible,start_value]body;,其中start_value是变量的初始值。其余同2。

循环语句可以嵌套。

选择语句

选择语句的格式是{block_1|block_2|...|block_n},在执行时,它会随机选择一个block来执行。

选择语句允许嵌套,也可以和循环语句嵌套。

一些例子

生成一棵树,以及树上的操作

input:
// 假设输入中的权值最大是2*10^18,该变量仅方便使用,不输出
W$(2*10^18)
// 结点数和操作数
n(100000) m(100000)\n
// 每个结点有一个初始的权值
[n]a(1, W) ;\n
// 随机生成树边,期望深度log n
[n-1, i]u(1, i) v(i+1)\n;
// 生成m个操作,假设操作有两种:
// 1 u v:询问u到v的路径上的点的权值和
// 2 u v w: 对u到v的路径上的点的权值+w
[m]{1 u(1, n) v(1, n)|2 u(1, n) v(1, n) w(1, W)}\n;

如果你想要树的深度比较大,可以

input:
...
// 随机生成树边,深度在n/2量级
[n/2-1, i, 2]u(i-1) v(i)\n;
[n-n/2, i, n/2+1]u(1, i-1) v(i)\n;
...

假装生成一个排列

input:
n(1, 100000)\n
// 找一个与n互质的数
W$(1000000007 % n)
// 偏移
D$(1, n)
[n, i, D]a(W * i % n + 1) ;\n 

利用Judger制作测试数据

开启这个模式后,Judger不会再进行对拍,所以你只需确保生成数据的部分和你的程序是正确的。

如果你想利用Judger制作测试数据,那么请在JudgeInfo.txt里写下makedata:

这一部分可以由任意多行组成,其中每一行的格式是:

[-]n: Initialization

其中n是正整数,Initialization是由Judger的数据生成语言写成的初始化部分。

Judger会按顺序处理每一行。对于其中的一行,如果n前没有减号,那么这一行会告诉Judger要生成n组数据,然后在生成每组数据时,先执行Initialization,再调用input:下的代码(或者你的输入生成程序,如果你用的是Judger提供的模板,你会看到Judger传进来一个代表现在生成的数据是第几组的参数dataId)。如果n前有减号,那么表示生成至第n组数据,其他部分是一样的。

注意:Initializatio中的代码不会输出! 也就是说,你初始化的时候可以这样写

makedata:
10: n(100000) m(10^6)

但Judger在处理这一段时不会输出空格以及n,m的值。