首先你要会写一个叫$data.yml$的东西,

这里面记录了这道题的$subtask$计分策略

也告诉了评测姬这道题是提交答案还是$spj$还是交互题

那么,$YAML$语言是啥啊?

别问我,我也不会 本着会用能用就行的原则

给大家讲讲$LOJ$的$special\ jidge$怎么用

$yaml$里基本上的全部语法:

$Structure$通过空格来展示。$Sequence$里的项用$-$来代表,Map里的键值对用$:$分隔.

在$LOJ$我们需要写一份类似这样的$data.yml$文件:

(摘自 LOJ帮助 ,稍有改动)

subtasks:           # 定义subtask
- score: 30 # 这个子任务的分数(注意,所有子任务的总分必须为 100)
type: sum # 子任务类型,可选的值有 sum、min 和 mul.
cases: [1, 2, 3] # 测试点编号可为数字
- score: 30 # 另一个子任务
type: mul        #sum:求和 mul:求积之后折合回100 min:取最小值按百分比折合
cases: ['4', '5', '6'] # 测试点编号也可为字符串
inputFile: 'dat#.in' # 告诉评测姬你测试数据包中的输入文件
outputFile: 'dat#.ans' # 告诉评测姬你测试数据包中的输出文件
# 上述文件名中的 '#' 字符将被替换为测试点编号,eg:dat1.in,dat1.out # Special Judge 可省略
specialJudge:
language: cpp      #语言,这里用简称 
fileName: spj.cpp    #这里是你 答案检查器 的名子,后缀最好要和language一样(没试过不一样行不行)

语言简称:ccppcpp11csharphaskelljavalualuajitnodejspascalpython2python3rubyvalavbnetocam

这里开始举个栗子,$A+B\ problem$ ,$10$个测试点,为$data1.in,data1.out \~ data10.in,data10.out$。

然后

  对于30%的数据,a,b<=100;

  对于另30%的数据,a,b<=1000000;

  对于另40%的数据,a,b<=100000000000000000000000000000000000000000000000000000000000000000;

这时候,你的$data.yml$里就要这样写:

subtasks:
- score: 30
type: sum
cases: [1, 2, 3]
- score: 30
type: mul
cases: [4, 5, 6]
- score: 40
cases: [7, 8, 9, 10] inputFile: 'data#.in'
outputFile: 'data#.out'

然后对于某沙华大佬的那道题,需要有$spj$

subtasks:
- score: 12
type: sum
cases: ['01-14','02-1234','03-1234','04-14','05-1234','06-1234','07-1234','08-1234','09-14','10-1234','11-134','12p-1234','23p-1234']
- score: 15
type: sum
cases: ['02-1234','03-1234','05-1234','06-1234','07-1234','08-1234','10-1234','12p-1234','13-234','14-234','15-234','16-234','17-234','18-234','19-234','20-234','21-234','22-234','23p-1234','24-234','25-234','26-234','27-234','28-234','29-234','30-234','31-234','32-234','33-234','34-234']
- score: 23
type: sum
cases: ['02-1234','03-1234','05-1234','06-1234','07-1234','08-1234','10-1234','11-134','12p-1234','13-234','14-234','15-234','16-234','17-234','18-234','19-234','20-234','21-234','22-234','23p-1234','24-234','25-234','26-234','27-234','28-234','29-234','30-234','31-234','32-234','33-234','34-234','35-34','36-34','37-34','38-34','39-34','40-34','41-34','42-34']
- score: 50
type: sum
cases: ['01-14','02-1234','03-1234','04-14','05-1234','06-1234','07-1234','08-1234','09-14','10-1234','11-134','12p-1234','13-234','14-234','15-234','16-234','17-234','18-234','19-234','20-234','21-234','22-234','23p-1234','24-234','25-234','26-234','27-234','28-234','29-234','30-234','31-234','32-234','33-234','34-234','35-34','36-34','37-34','38-34','39-34','40-34','41-34','42-34','43-4','44-4','45-4','46-4','47-4','48-4','49-4','50-4','51-4','52-4','53-4','54-4','55-4','56-4','57-4','58-4','59-4','60-4','61-4','62-4','63-4','64-4','65-4','66-4'] inputFile: 'demarcation.#.in'
outputFile: 'demarcation.#.sol' specialJudge:
- language: cpp11
fileName: spj_cpp11.cpp
 - language: cpp
   fileName: checker.cpp

(嘤嘤嘤这个数据点编号我也是醉了qwq)

下面开始讲讲怎么写$special\ judge$

只会C++

$Special\ Judge$ 程序运行时,其目录下会有四个文件 inputuser_outanswercode,分别对应该测试点的输入文件、用户输出、该测试点的输出文件、用户的代码(对于非提交答案题目)。

你可以从这四个文件里读入东西……

$Special\ Judge$ 程序运行完成后,应将该测试点的得分输出到标准输出(stdout)中(范围为 0100,将自动折合为测试点分数),并将提供给用户的额外信息输出到标准错误输出(stderr)中。

然后好像……

LOJ并不支持 $testlib.h$

$mdzz$

(本宝宝内心是拒绝给一个没$testlib.h$的OJ写$spj$的)

既然不支持,由于今天主要讲的是$LOJ$的$spj$写法

那我哭着也要写完吧……

上面说了,我们可以对那4个文件干一些事情

所以我这里只介绍输入输出怎么整,并不介绍运算(因为判断合法性要相对于题而言,并不能概括)

void read(char *fileName)
{
FILE *f = fopen(fileName, "r");
fscanf(f,...,...);
fclose(f);
}

调用这个函数的意思是:

从名为$fileName$的文件里读取一些东西

其中,

$fscanf(  )$里面先要有个$f,$之后就是$scanf$的格式。

之后就是给出正确、错误状态以及得分

void writ(const char s[],int point) {
//给出答案错误以及得分
/*
根据LOJ帮助里说,得分为stdout,详情为stderr
于是就用fprintf()来输出stderr,printf来输出得分
参数中,char数组表示的是详细信息的一个字符串,point是得分
*/
fprintf(stderr, "%s\n", s);
printf("%d\n",point);
exit();
}

然后就基础语法了

放上一波头文件

#include<cstdio>
#include<fstream>
#include<cstdlib>
#include<vector>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;

如果你不会写$data.yml$,但又想要$spj$,你需要在文件里包含一个 spj_***.xxx

其中,$***$为语言简称,$xxx$为任意后缀(强烈安利$.qwq$文件)

下面给出$a+b\ problem$的栗子:

#include<cstdio>
#include<fstream>
#include<cstdlib>
#include<vector>
#include<string>
#include<cctype>
#include<algorithm>
using namespace std;
int std_ans;
int per_out;
void read_ans(char *fileName)//从文件里读入一个数,存到std_ans里
{
FILE *f = fopen(fileName, "r");
fscanf(f,"%d",&std_ans);
fclose(f);
}
void read_out(char *fileName)//从文件里读入一个数,存到per_out里
{
FILE *f = fopen(fileName, "r");
fscanf(f,"%d",&per_out);
fclose(f);
}
void writ(const char s[],int point) {
fprintf(stderr, "%s\n", s);
printf("%d\n",point);
exit();
}
int main()
{
read_out("user_out");//从user_out,用户输出中读取per_out
read_ans("answer");//从 该测试点的输出文件 中读取 std_ans
if(std_ans==per_out) writ("ok the answer is corrit",);//返回正确
else writ("you are wrong",);//返回错误
}

到这里,基础教程就没了,高级的奇技淫巧还在后面……


你有没有发现,如果你要读一堆东西,发现你要写好多$read()$函数……

于是就崩溃了啊。

那怎么办呢?

魔改一下就好啊

int read_int(char *fileName)//从文件里读入一个数,返回这个数的值
{
FILE *f = fopen(fileName, "r");
int now;
fscanf(f,"%d",&now);
fclose(f);
return now;
}

这样我们就少写了好多东西哎

此时的$a+b$少了一个函数:

#include<cstdio>
#include<fstream>
#include<cstdlib>
#include<vector>
#include<string>
#include<cctype>
#include<algorithm>
using namespace std;
int std_ans;
int per_out;
int read_int(char *fileName)
{
FILE *f = fopen(fileName, "r");
int now;
fscanf(f,"%d",&now);
fclose(f);
return now;
}
void writ(const char s[],int point) {
fprintf(stderr, "%s\n", s);
printf("%d\n",point);
exit();
}
int main()
{
per_out=read_int("user_out");
std_ans=read_int("answer");
if(std_ans==per_out) writ("ok the answer is corrit",);
else writ("you are wrong",);
}

哇……这样我们是不是可以类比呢?

没错

char read_char(char *fileName)
{
FILE *f = fopen(fileName, "r");
char now;
fscanf(f,"%c",&now);
fclose(f);
return now;
}

当然,下面这个慎用……

下面这个慎用!!!

前面加 $#include<iostream>$

string resd_string(char *fileName)
{
freopen(fileName,"r",stdin);
string now;
cin>>now;
fclose(stdin);
return now;
}

这样是好写了……但是别忘了

$checker.cpp$运行也是有时间限制的啊啊啊、

所以……

你读一个数运行一次$fopen,fclose$可能会崩

所以你可以写一个指定从某文件读取$int,char$的函数。

这里我就不写了$qwq$


哇啊啊啊神tm LOJ支持$testlib.h$

那么就来讲讲$testlib.h$怎么用吧

首先我们需要有这个$testlib.h$

下载地址:戳这里

然后呢,我们需要的是

使用自定义校验器,请在problem.conf中去掉use_builtin_checker那一行。

(其实没什么用)

开始介绍$testlib.h$中的语法

首先必要的几个东西:

#include "testlib.h"
int main(int argc,char *argv[])
{
registerTestlibCmd(argc, argv);
/*
your main function
*/
return ;
}

第四行那句话是必须要加的,所谓的初始化$qwq$

不过,偷偷的告诉你,$testlib.h$里面包含的头文件:

#define random __random_deprecated
#include <stdlib.h>
#include <cstdlib>
#include <climits>
#include <algorithm>
#undef random #include <cstdio>
#include <cctype>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <sstream>
#include <fstream>
#include <cstring>
#include <limits>
#include <stdarg.h>
#include <fcntl.h>

所以基本上不用$#include$其他的东东。

之后,支持testlib.h$,就不用管之前的选手答案等东西的文件名了

$testlib.h$里面自带的文件名有这几个:

  • inf : 输入数据
  • ouf : 选手输出
  • ans : 标准输出

所以我们调用的话,直接$inf.***$ $ouf.***$ $ans.**$ 就好

下面说语法:

首先是读取

读取方法:

char readChar()

读入一个char。

char readChar(char c)

和上面一样,但是只能读到一个特定字母c

char readSpace()

读取一个空格同 readChar(' ').

string readToken()

读入一个字符串,但是遇到空格、换行、eof为止、

long long readLong()

读入一个$long\ long$

long long readLong(long long L, long long R)

同上,但是限定范围(包括L,R)

int readInt()

读入一个$int$

int readInt(int L, int R),

同上,但是限定范围(包括L,R)`

double readReal()

读入一个实数

double readReal(double L, double R),

同上,但是限定范围(包括L,R)

double readStrictReal(double L, double R, int minPrecision, int maxPrecision),

读入一个限定范围精度位数的实数。

string readString(),

string readLine()

读取一行string,到换行或者eof为止

void readEoln()

读入一个换行符

void readEof()

读入一个$eof$

int eof()

然后怎么调用这些呢?

我们从想要的文件里读入一个想要的类型的变量

就用$###.***$其中,$###$是文件名(上述三个),$***$是函数名(刚刚说的一堆)

举个例子,我们要从选手输出文件读取一个$int$

这么写就行了

int per_out=ouf.readInt();

这样就会从选手文件里读入一个$int$存到$per_out$里。

然后就是给出得分和答案

和$fprintf$不是一般的像,

这里用到的叫$qutif$和$quitp$函数,最少支持1个参数,最多……呵呵

格式:

$quitf(***,string,...)$

首先第一个参数是必须有的

$quitf$可选的值为:

.    \ok  //满分
. \wa //Wown answer ,0分
. double变量 //给选手a*100的分 (0<=a<=1)
. ceil(100.0*p/a)/ //给选手p分

中的$1,2$

$quitp$的第一个参数可以填3$,4$

quitf(\_ok, "The answer is correct. ");

给出AC

quitf(\_wa, "The answer is wrong");

给出WA

quitp(0.5,"Partially Correct");

给出$50\%$的分

quitp(ceil(100.0 * p / a) / 100, "QAQ");

这将会给选手p分。

之后那个字符串就是要显示的详情,里面遵循$printf$语法,就是支持 $\%d$等东西

然后后面跟着几个要显示的内容

这里口糊不太清楚,直接上代码

$a+b$的$spj$就可以这么写:

ps:这个直接从简介里抄了一份,请见谅

#include "testlib.h"
int main(int argc, char* argv[])
{
registerTestlibCmd(argc, argv);
int pans,jans;
pans=ouf.readInt();
jans=ans.readInt();
if (pans == jans)
quitf(_ok, "Correct. the answer is: %d \n QAQ " , jans);
else
quitf(_wa, "WA! expect=%d recieve=%d", jans, pans);
}

之后,多看几份$spj$就能自己写一个不错的$spj$了

然后呢……

下面奉上一份某沙华大佬的$spj$

额……某沙华大佬表示已经没题了

不,是沙华不会写QWQ

(强烈吐槽一句:LOJ的压榨翻译组的人力工作qwq)

如何给LOJ补全special judge的更多相关文章

  1. [LeetCode] Design Search Autocomplete System 设计搜索自动补全系统

    Design a search autocomplete system for a search engine. Users may input a sentence (at least one wo ...

  2. Mac OS终端中设置颜色高亮和自动补全

    已测试通过,原文:http://blog.csdn.net/songjinshi/article/details/8945809 一.颜色高亮显示 针对terminal采用bash模式: 编辑 ~/. ...

  3. 【bzoj2764】[JLOI2011]基因补全 dp+高精度

    题目描述 在生物课中我们学过,碱基组成了DNA(脱氧核糖核酸),他们分别可以用大写字母A,C,T,G表示,其中A总与T配对,C总与G配对.两个碱基序列能相互匹配,当且仅当它们等长,并且任意相同位置的碱 ...

  4. [LeetCode] 642. Design Search Autocomplete System 设计搜索自动补全系统

    Design a search autocomplete system for a search engine. Users may input a sentence (at least one wo ...

  5. Docker Compose的安装及命令补全

    安装Compose Compose的安装有多种方式,例如通过shell安装.通过pip安装.以及将compose作为容器安装等等.本文讲解通过shell安装的方式.其他安装方式如有兴趣,可以查看Doc ...

  6. Oracle补全日志(Supplemental logging)

    Oracle补全日志(Supplemental logging)特性因其作用的不同可分为以下几种:最小(Minimal),支持所有字段(all),支持主键(primary key),支持唯一键(uni ...

  7. python 添加tab补全

    在平时查看Python方法用到tab补全还是很方便的. 1. mac 平台 配置如下: mac是类Unix平台,需要在添加一条配置内容到bash_profile 中(默认是没有这个文件,可以新建一个放 ...

  8. 记录一次bug解决过程:else未补全导致数据泄露和代码优化

    一.总结 快捷键ctrl + alt + 四个方向键 --> 倒置屏幕 未补全else逻辑,倒置查询数据泄露 空指针是最容易犯的错误,数据的空指针,可以普遍采用三目运算符来解决 SVN冲突解决关 ...

  9. jQuery 邮箱下拉列表自动补全

    综述 我想大家一定见到过,在某个网站填写邮箱的时候,还没有填写完,就会出现一系列下拉列表,帮你自动补全邮箱的功能.现在我们就用jQuery来实现一下. 博主原创代码,如有代码写的不完善的地方还望大家多 ...

随机推荐

  1. sqlplus 方式连接 远程数据库

    方式一:简易连接,不用进行网络配置,其实就是tnsname.ora文件,但只支持oracle10G以上.命令:sqlplus 用户名/密码@ip地址[:端口]/service_name [as sys ...

  2. javascript 对象的扩展性

    javascript 对象 的可扩展性 javascript 对象中的可扩展性指的是:是否可以给对象添加新属性.所有的内置对象和自定义对象显示的都是可扩展的,对于宿主对象,则有javascript 引 ...

  3. cf520B-Two Buttons 【BFS】

    http://codeforces.com/contest/520/problem/B Two Buttons Vasya has found a strange device. On the fro ...

  4. C# Action

    Action<T> Delegate Encapsulates a method that has a single parameter and does not return a val ...

  5. React Native开源项目案例

    (六).React Native开源项目: 1.Pober Wong_17童鞋为gank.io做的纯React Native项目,开源地址:https://github.com/Bob1993/Rea ...

  6. C++11中std::unordered_map的使用

    unordered map is an associative container that contains key-value pairs with unique keys. Search, in ...

  7. BETTER SUPPORT FOR FUNCTIONAL PROGRAMMING IN ANGULAR 2

    In this blog post I will talk about the changes coming in Angular 2 that will improve its support fo ...

  8. android studio快捷键大全

    ----常用快捷键 1.Ctrl+E,可以显示最近编辑的文件列表 2.Shift+Click可以关闭文件 3.Ctrl+[或]可以跳到大括号的开头结尾 4.Ctrl+Shift+Backspace可以 ...

  9. WebClient使用与IIS7最大上传文件--升级&引导窗口&目录同步完整解决方法

    IIS7最大上传文件说明:http://www.mzwu.com/article.asp?id=2449 WebClient使用说明使用using  及时回收资源 using(var wc=new W ...

  10. BZOJ 2002 Bounce 弹飞绵羊 (分块或动态树)

    2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 13768  Solved: 6989[Subm ...