↵
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 is really easy to write a validator using testlib.h.↵
↵
## Example↵
↵
Following is the validator 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();↵
↵
for (int i = 0; i < testCount; i++) {↵
int n = inf.readInt(1, 100, "n");↵
inf.readChar(' ');↵
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(' ');↵
}↵
inf.readEoln();↵
}↵
↵
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).↵
- **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.|↵
↵
↵
#### 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
Это естественно, что вы будете себя так чувствовать. Даже опытные авторы задач не застрахованы от ошибок (это случается даже на самых престижных соревнованиях: пример тому — финал чемпионата мира ACM ICPC 2007 г.)↵
↵
Настоятельно рекомендуется писать специальную программу (называемую валидатором), чтобы формально проверить каждый тест на соответствие всем требованиям условия задачи.↵
Валидаторы обязательны для задач, которые готовятся для Codeforces. [Polygon](https://polygon.codeforces.com) имеет встроенную поддержку валидаторов.↵
↵
Написать валидатор с помощью testlib.h на самом деле очень легко. ↵
↵
## Пример↵
↵
Ниже приводится валидатор, который была написан для задачи [problem:100541A]:↵
↵
~~~~~↵
#include "testlib.h"↵
#include <bits/stdc++.h>↵
using namespace std;↵
↵
int main() {↵
registerValidation();↵
int testCount = inf.readInt(1, 10, "testCount");↵
inf.readEoln();↵
↵
for (int i = 0; i < testCount; i++) {↵
int n = inf.readInt(1, 100, "n");↵
inf.readChar(' ');↵
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(' ');↵
}↵
inf.readEoln();↵
}↵
↵
inf.readEof();↵
}↵
↵
~~~~~↵
↵
Самое замечательное в этом валидаторе то, что он очень простой, и в нем очень трудно написать что-то неправильно.↵
↵
В репозитории Github можно найти другие [примеры валидаторов](https://github.com/MikeMirzayanov/testlib/tree/master/validators).↵
↵
## Функции и методы↵
↵
Первая строка вашего кода должна содержать вызов `registerValidation()`: немного магии, и вы можете использовать необходимые методы. ↵
↵
[cut]↵
↵
Большинство методов для валидатора начинаются с префикса _read_ и именно выполняют чтение: перемещают указатель во входном потоке на следующую позицию после прочтения чего-либо. В процессе чтения обнаруживаются нарушения (входные данные не соответствуют тому, что вы пытаетесь прочитать: например, вы предпринимаете попытку прочитать целое число, а во входных данных встречается строка) и выбрасывается ошибка.↵
↵
**Замечания**:↵
↵
- Валидатор строг. Он проверяет корректное расположение пробелов. Например, последовательность вызовов вида _прочесть число_, _прочесть пробел_, _прочесть число_ гарантирует наличие ровно одного пробела между числами; в противном случае валидатор сообщит об ошибке.↵
- Некоторые методы частично поддерживают синтаксис регулярных выражений. Конечно, это не полноценные регулярные выражения, которые вы можете использовать во многих языках программирования. Это очень простая версия, в которой поддерживается следующее:↵
- **Множество** символов: например, `[a-z]` — любые строчные латинские буквы, `[^a-z]` — любые символы за исключением строчных латинских букв.↵
- **Диапазон**, например, шаблон `[a-z]{1,5}` описывает строки длиной от 1 до 5 символов, содержащие только строчные латинские буквы.↵
- Оператор **Или**, например, шаблон `mike|john` — это или строка `mike`, или строка `john`.↵
- **Необязательные** символы, например, шаблон `-?[1-9][0-9]{0,3}` допускает ненулевые целые числа от -9999 до 9999 (обратите внимание на необязательный знак "минус").↵
- **Повторения**, например, шаблон `[0-9]*` допускает последовательности (как пустые, так и непустые) цифр, а шаблон `[0-9]+` только непустые последовательности цифр.↵
- Также заметим, что при распознавании регулярных выражений используется очень простой жадный алгоритм. Например, шаблон `[0-9]?1` не допускает `1` в силу жадного поведения распознавателя.↵
↵
Ниже представлен полный список функций и методов↵
↵
|Метод / функция|Что делает|↵
|-|-|↵
|void registerValidation()| Эта функция должна быть вызвана в начале вашего кода, чтобы использовать валидатор. После вызова этой функции вы получаете доступ к входному потоку посредством переменной `inf`. |↵
|char readChar()| Этот метод возвращает текущий символ и перемещает указатель на один символ вперед.|↵
|char readChar(char c)| Аналогичен `readChar()`, но обеспечивает проверку, что прочитанный символ именно `c`.|↵
|char readSpace()| Аналогичен `readChar(' ')`.|↵
|void unreadChar(char c)| Возвращает символ `c` во входной поток.|↵
|string readToken()|Читает и возвращает очередную лексему (токен).|↵
|string readToken(string regex)|Аналогичен `readToken()`, но выполняет проверку соответствия лексемы (токена) указанному регулярному выражению `regex`.|↵
|long long readLong()|Читает и возвращает длинное целое (`long long` в C/C++ и `long` в Java)|↵
|long long readLong(int L, int R)|Аналогичен `readLong()`, но выполняет проверку, что значение находится в диапазоне $[L, R]$ (включительно)|↵
|int readInt(), <br> int readInteger()|Читает и возвращает целое число (тип `int` как в Java, так и в C/C++)|↵
|int readInt(int L, int R), <br> int readInteger(L, R)|Аналогичны `readInt()`, но выполняет проверку, что значение находится в диапазоне $[L, R]$ (включительно)|↵
|double readReal(), <br> double readDouble()|Читают и возвращают вещественное число (`double`).|↵
|double readReal(double L, double R), <br> double readDouble(double L, double R)|Аналогичны `readReal()`, `readDouble()`, но выполняют проверку, что значение находится в диапазоне $[L, R]$.|↵
|double readStrictReal(double L, double R, int minPrecision, int maxPrecision), <br> double readStrictDouble(double L, double R, int minPrecision, int maxPrecision)|Аналогичны `readReal(L, R)`, `readDouble(L, R)`, но выполняют дополнительную проверку, что количество цифр после десятичной точки находится в диапазоне $[minPrecision, maxPrecision]$. Экспоненциальная запись числа или другие нестандартные формы записи не допускаются.|↵
|string readString(), <br> string readLine()|Прочитывают строку, начиная с текущей позиции до EOLN. Перемещают указатель во входном потоке на первый символ следующей строки (если она существует).|↵
|string readString(string regex), <br> string readLine(string regex)|Аналогичны `readString()` and `readLine()`, но выполняют проверку, что строка соответствует указанному регулярному выражению `regex`.|↵
|void readEoln()|Читает EOLN или завершает работу с ошибкой. Заметим, что этот метод чудесным образом работает как для Windows, так и для Linux. В Windows он прочитывает #13#10, а в Linux #10.|↵
|void readEof()|Читает EOF или завершает работу с ошибкой.|↵
↵
↵
#### Параметр _variableName_↵
↵
Рекомендуется использовать последний строковый параметр _variableName_ в методах readInt/readInteger/readLong/readDouble/readWord/readToken/readString/readLine, чтобы сделать сообщение об ошибке более удобным для чтения. Т.е. предпочтительнее использовать `inf.readInt(1, 100, n)` вместо `inf.readInt(1, 100)`. При возникновении ошибки в первом случае будет выводиться сообщение вида `FAIL Integer parameter [name=n] equals to 0, violates the range [1, 100]`.↵
↵
#### Использование _ensure/ensuref_↵
↵
Чтобы проверить некоторые требования (например, то, что граф не содержит петель, т.е. что $x_i \ne y_i$), используйте `ensuref(x_i != y_i, "Graph can't contain loops")`. Допускается использование спецификаторов формата языка C, подобных `ensuref(s.length() % 2 == 0, "String 's' should have even length, but s.length()=%d", int(s.length()))`.↵
Также вы можете использовать более простую форму `ensure(x > y)`, в этом случае будет печататься нарушенное условие, если оно не выполняется: `FAIL Condition failed: "x > y"`.↵
↵
Ссылки: [страница testlib.h на Github](https://github.com/MikeMirzayanov/testlib/blob/master/testlib.h)↵