Skip to content

General

This page introduces some common states/objects/functions, usage, and precautions for Testlib checker/interactor/validator. Please read this page completely before reading other pages.

Common States

Result Testlib Alias Meaning
Ok _ok Correct answer.
Wrong Answer _wa Wrong answer.
Presentation Error _pe Presentation error. Note that many OJs, including Codeforces, do not distinguish between PE and WA.
Partially Correct _pc(score) Partially correct. Only for test cases with partial scores, where score is a positive integer from \(0\) (no points) to \(100\) (maximum possible score). (quitf+_pc is only for compatibility with old pascal-testlib; if you want to output partial scores, it is recommended to use quitp1)
Fail _fail In validator: indicates the input is invalid and fails validation.
In checker: indicates an internal program error, incorrect standard output, or contestant output being better than the standard output, requiring attention from judges/problem setters (i.e., a problem bug).

Usually, the program's return value indicates the result, but there are other methods: creating an output XML file, outputting information to stdout, or other locations... These are all done via the quitf function in the function table below.

Common Objects

Object Meaning
inf Input file stream
ouf Contestant output stream
ans Reference output stream

Common Functions

Non-member functions:

Call Meaning
void registerTestlibCmd(int argc, char* argv[]) Register the program as a checker
void registerInteraction(int argc, char* argv[]) Register the program as an interactor
void registerValidation()/void registerValidation(int argc, char* argv[]) Register the program as a validator
void registerGen(int argc, char* argv[], int randomGeneratorVersion) Register the program as a generator
randomGeneratorVersion is recommended to be 1
void quit(TResult verdict, string message)/void quitf(TResult verdict, string message, ...) End the program, return verdict, and output message
void quitif(bool condition, TResult verdict, string message, ...) If condition is true, call quitf(verdict, message, ...)
void quitp(F points, string message, ...) End the program and return partial scores. For most OJs (e.g., Luogu, UOJ), points requires a real number in \([0,1]\), representing the score percentage. Some OJs (e.g., Lyrio) require points to be a real number in \([0,100]\) (the OJ automatically discards the decimal part), representing the score out of 100 for the test case.

Stream member functions:

Call Meaning
char readChar() Read a character
char readChar(char c) Read a character, must be c
char readSpace() Equivalent to readChar(' ')
string readToken()/string readWord() Read a string until a whitespace character (space, tab, EOLN, etc.)
string readToken(string regex)/string readWord(string regex) Read a string, must match regex
long long readLong() Read a 64-bit integer
long long readLong(long long L, long long R) Read a 64-bit integer, must be in \([L,R]\)
vector<long long> readLongs(int n, long long L, long long R) Read \(N\) 64-bit integers, all must be in \([L,R]\)
int readInt()/int readInteger() Read a 32-bit integer
int readInt(int L, int R)/int readInteger(L, R) Read a 32-bit integer, must be in \([L,R]\)
vector<int> readInts(int n, int L, int R)/vector<int> readIntegers(int n, int L, int R) Read \(N\) 32-bit integers, all must be in \([L,R]\)
double readReal()/double readDouble() Read a double-precision floating-point number
double readReal(double L, double R)/double readDouble(double L, double R) Read a double-precision floating-point number, must be in \([L,R]\)
double readStrictReal(double L, double R, int minPrecision, int maxPrecision)/double readStrictDouble(double L, double R, int minPrecision, int maxPrecision) Read a double-precision floating-point number, must be in \([L,R]\), decimal places must be in \([minPrecision,maxPrecision]\), and must not use non-standard formats like exponential notation
string readString()/string readLine() Read a line (including the newline character) and move the stream pointer to the beginning of the next line
string readString(string regex)/string readLine(string regex) Read a line, must match regex
void readEoln() Read EOLN (reads LF on Linux, CR LF on Windows)
void readEof() Read EOF
void quit(TResult verdict, string message)/void quitf(TResult verdict, string message, ...) End the program; if Stream is ouf, return verdict, otherwise return _fail; output message
void quitif(bool condition, TResult verdict, string message, ...) If condition is true, call quitf(verdict, message, ...)

To be continued...

Minimal Regular Expressions

Some of the input functions above allow the use of "minimal regular expressions," as shown below:

  • Character sets. For example, [a-z] represents all lowercase English letters, [^a-z] represents any character except lowercase English letters.
  • Ranges. For example, [a-z]{1,5} represents a string of length between \([1,5]\) containing only lowercase English letters.
  • "Or" identifier. For example, mike|john represents either mike or john.
  • "Optional" identifier. For example, -?[1-9][0-9]{0,3} represents non-zero integers in the range \([-9999,9999]\) (note the optional minus sign).
  • "Repeat" identifier. For example, [0-9]* represents zero or more digits, [0-9]+ represents one or more digits.
  • Note that the regular expressions here are "greedy" ("repeat" will match as much as possible). For example, [0-9]?1 will not match 1 (because [0-9]? matches the 1, leaving the remaining 1 in the template unmatched).

Include testlib.h First

Make sure testlib.h is the first header you include. Testlib will rewrite/disable (via name conflicts) some random-related functions (e.g., random()), ensuring that random results are environment-independent. This is very important for generators, as explained in detail on the generator page.

Use Item Aliases

It is recommended to add an extra string parameter as the alias for the currently read item to the constrained calls of readInt/readInteger/readLong/readDouble/readWord/readToken/readString/readLine, etc., to make error messages more readable. For example, use inf.readInt(1, 100, "n") instead of inf.readInt(1, 100). The error message will then be FAIL Integer parameter [name=n] equals to 0, violates the range [1, 100].

Use ensuref/ensure()

These two functions are used to check whether a condition holds (similar to assert()). For example, to check \(x_i \neq y_i\), we can use

1
ensuref(x[i] != y[i], "Graph can't contain loops");

You can also use C-style placeholders, such as

1
2
3
ensuref(s.length() % 2 == 0,
        "String 's' should have even length, but s.length()=%d",
        int(s.length()));

There is a simplified version ensure(). You can directly use ensure(x > y) without adding explanatory content (and it does not support adding explanatory content). If the condition is not met, the error will be FAIL Condition failed: "x > y". In many cases, such errors without additional explanation are not user-friendly, so we usually use ensuref() with explanatory content instead of ensure().

Warning

Note the difference between global and member ensuref/ensure().

The global functions ::ensuref/ensure() are mostly used in generators and validators. If the check fails, they uniformly return _fail.

The member functions InStream::ensuref/ensure() are generally used to check whether contestant and reference outputs are valid. When InStream is ouf, they return _wa; when it is inf (generally, input data should not be checked in the checker; this should be done in the validator) or ans, they return _fail. For details, see Checker - Writing the readAns function.

This article is mainly translated and synthesized from the Testlib - Codeforces series. The GitHub repository for testlib.h is MikeMirzayanov/testlib.