If you have written some taskprogramming problems, and have prepared test cases, you will probably experience the terrible feeling that some test cases may be invalid (meaning it does not agree with the constraints in problem statement): upper bound can be violated, your graph not satisfied connectivity requirements or is not at tree... It is reasonable to feel that way. Even experienced problem setters make mistakes sometimes (for example, in the prestigious ACM ICPC World final 2007).↵
↵
The validator in testlib is a good tool to help you prevent such mistakes. It is strictly recommended to write a special program (called _validator_) to formally check each test to satisfy all requirements from problem statements. Validators are strictly required for problems on Codeforces. [Polygon](https://polygon.codeforces.com) has built-in support of validators.↵
↵
It isverreally easy to usewrite a validator using testlib.h.↵
↵
## Example↵
=======↵
↵
Following is the validatorof validator, which I used in a problem I prepared:was written for the problem [problem:100541A]:↵
↵
↵
~~~~~↵
#include "testlib.h"↵
#include <bits/stdc++.h>↵
using namespace std;↵
↵
int main() {↵
registerValidation();↵
int testCount = inf.readInt(1, 10, "testCount");↵
inf.readEoln();↵
↵
while (test--for (int i = 0; i < testCount; i++) {↵
int n = inf.readInt(1, 100, "n");↵
inf.readChar(' ');↵
int w = inf.readInt(1, 1000000, "w");↵
inf.readEoln();↵
↵
for(int i = 0; i < n; ++i) {↵
inf.readInt(1, 1000, "p_i");↵
if (i < n-1) inf.readChar(' ');↵
}↵
else inf.readEoln();↵
}↵
}↵
↵
inf.readEof();↵
return 0;↵
}↵
↵
~~~~~↵
↵
The wonderful thing about this validator is that it is very simple and it is very difficult to write something incorrect.↵
↵
More examples can be found at [the Github repo](https://github.com/MikeMirzayanov/testlib/tree/master/validators)↵
↵
## Available methods↵
==========================↵
↵
The first line of your code should be `registerValidation()` which does some magic in the background, so that you can use the necessary methods.↵
↵
[cut]↵
↵
Most methods for validators start with prefix "read" and it does the same thing: moves input stream pointer to next suitable place after reading something. It also detect violations (input does not match what you are trying to read), and then throw error.↵
↵
**Notes**:↵
↵
- Validator is strict. It cares about correct placing of spaces. For example, when you're trying to read an integer and the next character is a space (and then an integer), the validator will throw error.↵
- Some method has "regex" feature. It is not a full-featured regex as you may have used in many programming languages. It is a very simple version, which supports the following:↵
- **Set** of character, e.g: `[a-z]` is a lowercase latin letter, `[^a-z]` matches anything but a lowercase latin letter.↵
- **Range**, e.g. `[a-z]{1,5}` is a string of length 1 to 5 consists of only lowercase latin letter.↵
- **Or** operator, e.g. `mike|john` is either `mike` or `john`.↵
- **Optional** character, e.g. `-?[1-9][0-9]{0,3}` will match non-zero integers from -9999 to 9999 (note the optional minus sign), note that it will match '-0'.↵
- **Repetition**, e.g. `[0-9]*` will match sequences (empty or non-empty) of digits, and `[0-9]+` will match non-empty sequences of digits.↵
- Also regarding regex, very simple greedy algorithm is used. For example, pattern `[0-9]?1` will not match `1`, because of greedy nature of matching.↵
↵
Following is full list of methods available:↵
↵
|Method|What it does|↵
|-|-|↵
|void registerValidation()| This method must be called at the beginning of your code in order to use validator. <br> After calling this method, you can access input stream by variable named `inf`. |↵
|char readChar()| Returns current character and moves pointer one character forward.|↵
|char readChar(char c)| Same as `readChar()` but ensures that the readCharacter is 'c'.|↵
|char readSpace()| Same as `readChar(' ')`.|↵
|void unreadChar(char c)| Puts back character c to input stream.|↵
|string readToken()|Reads a new token.|↵
|string readToken(string regex)|Same as `readToken()` but ensures that it matches given regex.|↵
|long long readLong()|Reads a long (long long in C/C++ and long in Java)|↵
|long long readLong(int L, int R)|Same as `readLong()` but ensures that the value is in range $[L, R]$ (inclusively)|↵
|int readInt(), <br> int readInteger()|Reads an integer (int type in both Java and C/C++)|↵
|int readInt(int L, int R), <br> int readInteger(L, R)|Same as `readInt()` but ensures that the value is in range $[L, R]$ (inclusively)|↵
|double readReal(), <br> double readDouble()|Reads a double.|↵
|double readReal(double L, double R), <br> double readDouble(double L, double R)|Same as `readReal()`, `readDouble()` but ensures that the value is in range $[L, R]$.|↵
|double readStrictReal(double L, double R, int minPrecision, int maxPrecision), <br> double readStrictDouble(double L, double R, int minPrecision, int maxPrecision)|Same as `readReal(L, R)`, `readDouble(L, R)`, but additionally ensures that the number of digits after decimal point is between $[minPrecision, maxPrecision]$. Doesn't allow exponential or any other non-standard form.|↵
|string readString(), <br> string readLine()|Reads a line from current position to EOLN. Moves input stream pointer to first character of new line (if exists).|↵
|string readString(string regex), <br> string readLine(string regex)|Same as `readString()` and `readLine()`, but ensures that the string matches given regex.|↵
|void readEoln()|Reads EOLN or fails. Note that this method magically works on both Windows and Linux. On Windows it reads #13#10 and on Linux it reads #10.|↵
|void readEof()|Reads EOF or fails.|↵
↵
↵
These methods are also useful in writing checkers#### Parameter _variableName_↵
It is recommended to insert last string parameter to readInt/readInteger/readLong/readDouble/readWord/readToken/readString/readLine called _variableName_ to make error message be human-readable. So it is preffered to use `inf.readInt(1, 100, n)` instead of `inf.readInt(1, 100)`. The first statement will fail with human-readable message like `FAIL Integer parameter [name=n] equals to 0, violates the range [1, 100]`.↵
↵
#### Using ensure/ensuref↵
↵
To check a requirement (like a graph doesn't contain loops, i.e. $x_i \ne y_i$) use `ensuref(x_i != y_i, "Graph can't contain loops")`. It is allowed to use C-language format specifiers like `ensuref(s.length() % 2 == 0, "String 's' should have even length, but s.length()=%d", int(s.length()))`. Also you can use simple form like `ensure(x > y)`, it will print failed condition if it doesn't hold in form `FAIL Condition failed: "x > y"`.↵
↵
↵
Reference: [Github page of testlib.h](https://github.com/MikeMirzayanov/testlib/blob/master/testlib.h)↵
↵
↵
It is
↵
## Example↵
Following is the validator
↵
#include "testlib.h"↵
#include <bits/stdc++.h>↵
using namespace std;↵
↵
int main() {↵
registerValidation();↵
int testCount = inf.readInt(1, 10, "testCount");↵
inf.readEoln();↵
↵
int n = inf.readInt(1, 100, "n");↵
inf.readChar(' ');↵
inf.readEoln();↵
↵
for(int i = 0; i < n; ++i) {↵
inf.readInt(1, 1000, "p_i");↵
if (i < n-1) inf.readChar(' ');↵
}↵
↵
inf.readEof();↵
↵
~~~~~↵
↵
The wonderful thing about this validator is that it is very simple and it is very difficult to write something incorrect.↵
↵
More examples can be found at [the Github repo](https://github.com/MikeMirzayanov/testlib/tree/master/validators)↵
↵
## Available methods↵
The first line of your code should be `registerValidation()` which does some magic in the background, so that you can use the necessary methods.↵
↵
[cut]↵
↵
Most methods for validators start with prefix "read" and it does the same thing: moves input stream pointer to next suitable place after reading something. It also detect violations (input does not match what you are trying to read), and then throw error.↵
↵
**Notes**:↵
↵
- Validator is strict. It cares about correct placing of spaces. For example, when you're trying to read an integer and the next character is a space (and then an integer), the validator will throw error.↵
- Some method has "regex" feature. It is not a full-featured regex as you may have used in many programming languages. It is a very simple version, which supports the following:↵
- **Set** of character, e.g: `[a-z]` is a lowercase latin letter, `[^a-z]` matches anything but a lowercase latin letter.↵
- **Range**, e.g. `[a-z]{1,5}` is a string of length 1 to 5 consists of only lowercase latin letter.↵
- **Or** operator, e.g. `mike|john` is either `mike` or `john`.↵
- **Optional** character, e.g. `-?[1-9][0-9]{0,3}` will match non-zero integers from -9999 to 9999 (note the optional minus sign), note that it will match '-0'.↵
- **Repetition**, e.g. `[0-9]*` will match sequences (empty or non-empty) of digits, and `[0-9]+` will match non-empty sequences of digits.↵
- Also regarding regex, very simple greedy algorithm is used. For example, pattern `[0-9]?1` will not match `1`, because of greedy nature of matching.↵
↵
Following is full list of methods available:↵
↵
|Method|What it does|↵
|-|-|↵
|void registerValidation()| This method must be called at the beginning of your code in order to use validator. <br> After calling this method, you can access input stream by variable named `inf`. |↵
|char readChar()| Returns current character and moves pointer one character forward.|↵
|char readChar(char c)| Same as `readChar()` but ensures that the readCharacter is 'c'.|↵
|char readSpace()| Same as `readChar(' ')`.|↵
|void unreadChar(char c)| Puts back character c to input stream.|↵
|string readToken()|Reads a new token.|↵
|string readToken(string regex)|Same as `readToken()` but ensures that it matches given regex.|↵
|long long readLong()|Reads a long (long long in C/C++ and long in Java)|↵
|long long readLong(int L, int R)|Same as `readLong()` but ensures that the value is in range $[L, R]$ (inclusively)|↵
|int readInt(), <br> int readInteger()|Reads an integer (int type in both Java and C/C++)|↵
|int readInt(int L, int R), <br> int readInteger(L, R)|Same as `readInt()` but ensures that the value is in range $[L, R]$ (inclusively)|↵
|double readReal(), <br> double readDouble()|Reads a double.|↵
|double readReal(double L, double R), <br> double readDouble(double L, double R)|Same as `readReal()`, `readDouble()` but ensures that the value is in range $[L, R]$.|↵
|double readStrictReal(double L, double R, int minPrecision, int maxPrecision), <br> double readStrictDouble(double L, double R, int minPrecision, int maxPrecision)|Same as `readReal(L, R)`, `readDouble(L, R)`, but additionally ensures that the number of digits after decimal point is between $[minPrecision, maxPrecision]$. Doesn't allow exponential or any other non-standard form.|↵
|string readString(), <br> string readLine()|Reads a line from current position to EOLN. Moves input stream pointer to first character of new line (if exists).|↵
|string readString(string regex), <br> string readLine(string regex)|Same as `readString()` and `readLine()`, but ensures that the string matches given regex.|↵
|void readEoln()|Reads EOLN or fails. Note that this method magically works on both Windows and Linux. On Windows it reads #13#10 and on Linux it reads #10.|↵
|void readEof()|Reads EOF or fails.|↵
↵
↵
It is recommended to insert last string parameter to readInt/readInteger/readLong/readDouble/readWord/readToken/readString/readLine called _variableName_ to make error message be human-readable. So it is preffered to use `inf.readInt(1, 100, n)` instead of `inf.readInt(1, 100)`. The first statement will fail with human-readable message like `FAIL Integer parameter [name=n] equals to 0, violates the range [1, 100]`.↵
↵
#### Using ensure/ensuref↵
↵
To check a requirement (like a graph doesn't contain loops, i.e. $x_i \ne y_i$) use `ensuref(x_i != y_i, "Graph can't contain loops")`. It is allowed to use C-language format specifiers like `ensuref(s.length() % 2 == 0, "String 's' should have even length, but s.length()=%d", int(s.length()))`. Also you can use simple form like `ensure(x > y)`, it will print failed condition if it doesn't hold in form `FAIL Condition failed: "x > y"`.↵
↵
↵
Reference: [Github page of testlib.h](https://github.com/MikeMirzayanov/testlib/blob/master/testlib.h)↵