Checker
Checker, also known as Special Judge, is used to verify whether an answer is valid. Using Testlib can save us from checking many things, making the implementation much simpler.
A Checker reads the input file name, the contestant's output file name, and the standard output file name from command-line arguments, determines whether the contestant's output is correct, and returns a predefined result.
Please read General before proceeding.
Simple Example
Problem
Given two integers \(a,b\) (\(-1000 \le a,b \le 1000\)), output their sum.
This problem obviously doesn't need a checker, but if one must write one:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
Writing the readAns Function
Suppose you have a problem where both input and output contain many numbers, e.g., given a DAG, find the longest path from \(s\) to \(t\) and output the path (multiple possible, output any one).
Below is an example of a bad checker.
Bad Implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | |
This checker has two main issues:
- It assumes the standard output is correct. If the contestant's output is better than the standard output, it will be judged as WA, which is not ideal. Also, if the standard output is invalid, it will also produce WA. For both cases, the correct action is to return the Fail status.
- The code for reading the standard output and the contestant's output is duplicated. In this problem, writing it twice is not a big deal—just a
forloop—but if a problem has complex output, it will make the checker structure messy. Duplicate code greatly reduces maintainability and makes debugging or format modifications difficult.
The way to read the standard output and the contestant's output is actually identical, which is why we usually write a reading function that takes a stream as a parameter.
Good Implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
Note that with this approach we also check whether the standard output is valid. Writing the checker this way makes the program shorter and easier to understand and debug. This approach is also suitable for problems that output YES (and possibly a solution) or NO.
Note
For checking certain constraints, the InStream::ensure/ensuref() functions can be used more concisely. For example, lines 23 to 25 above can be equivalently written as:
1 | |
Warning
Avoid calling global functions ::ensure/ensuref() in readAns, as this may cause _fail to be returned for contestant outputs that should be judged as WA, leading to errors.
Suggestions and Common Mistakes
-
Write the
readAnsfunction; it can really make your checker great. -
Always specify ranges when reading contestant output. If some variables are not range-checked and are used as parameters, your checker may judge incorrectly or cause RE.
- Bad Example
1 2 3 4 5 6 7 8 9 10
// .... int k = ouf.readInt(); vector<int> lst; for (int i = 0; i < k; i++) // k = 0 and k = -5 behave the same here (loop body not entered) lst.push_back(ouf.readInt()); // But we don't want to accept a list of length -5, right? // .... int pos = ouf.readInt(); int x = A[pos]; // Someone might output -42, 2147483456, or other illegal numbers causing checker RE- Good Example
1 2 3 4 5 6 7 8
// .... int k = ouf.readInt(0, n); // Invalid length will immediately judge WA instead of continuing check and causing RE vector<int> lst; for (int i = 0; i < k; i++) lst.push_back(ouf.readInt()); // .... int pos = ouf.readInt(0, (int)A.size() - 1); // Prevent out of range int x = A[pos]; // .... -
Use item aliases.
-
Unlike validators, checkers do not need to specifically check for non-whitespace characters. For example, for a checker that compares integers in order, we only need to check whether the contestant's output integers correspond to the answer integers. Whether the contestant outputs one integer per line or all integers on one line is a formatting issue that our checker does not need to care about.
Usage
Usually, we don't need to run it locally; the judging tool/OJ will handle it for us. But if needed, run it on the command line in the following format:
1 | |
Some Preset Checkers
Often, our checker's task is simple (e.g., checking if output integers are correct, or if output floating-point numbers meet precision requirements). Testlib has already provided implementations for these checkers, which we can use directly.
Some commonly used checkers are:
- ncmp: Compare 64-bit integers in order.
- rcmp4: Compare floating-point numbers in order, with maximum acceptable error (absolute or relative) not exceeding \(10^{-4}\) (there are also rcmp6, rcmp9, etc., for different precision requirements, used similarly to rcmp4).
- wcmp: Compare strings in order (ignoring spaces, newlines, and other non-whitespace characters).
-
yesno: Compare YES and NO, case-insensitive.
This article is mainly translated from Checkers with testlib.h - Codeforces. The GitHub repository for
testlib.his MikeMirzayanov/testlib.
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:OI-wiki
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用