Бібліотека Алготестер | Статті

Бібліотеки algotester.h та algotester_generator.h створені для полегшення написання першоджерел до задач. Використовуйте їх при написанні всіх перевірників, достовірників, оцінювачів та генераторів тестів.

Бібліотека algotester.h

Під час використання бібліотеки Ви працюватимете з класом AlgotesterReader. Це клас для зчитування даних. При зчитуванні він також може перевіряти різні властивості. Цей зчитувач працює у двох режимах: строгий для перевірників та нестрогий для достовірників й оцінювачів. У строгому режимі потрібно перевіряти формат даних включно з пробілами та символами кінця рядка. У нестрогому окремо зчитувати пробіли чи символи кінця рядка непотрібно.

Список методів класу AlgotesterReader та їх короткий опис:

  • readChar — зчитує один символ. В нього можна передати список можливих значень, чи нехтувати пробільними символами (не можна в строгому режимі) та назву змінної яку зчитуємо. Повертає символ, який зчитали, або видає помилку, якщо щось пішло не так. Якщо символ може приймати довільні значення, то як список можливих треба передати порожній рядок.

  • readSpace — зчитує один пробіл. Потрібно робити в строгому режимі.

  • readEndl — зчитує символ кінця рядка. Потрібно робити в строгому режимі.

  • readEof — зчитує символ кінця файлу. Потрібно завжди робити у перевірнику та достовірнику з потоку користувача, щоб переконатися у відсутності зайвого виводу.

  • isEof — перевіряє чи вже кінець файлу. Приймає параметр чи нехтувати пробільними символами (не можна в строгому режимі). Якщо нехтувати пробільними символами, то повертає true, якщо залишилися лише пробільні символи.

  • readInt — повертає ціле 64-бітне число. Може приймати параметри нижню та верхню межі включно та назву змінної яку зчитуємо. Наприклад int n = reader.readInt(2, 100000, "n"); зчитає змінну \(n\), та перевірить чи вона є в межах від 2 до \(10^5\).

  • readVectorInt — повертає вектор цілих 64-бітних чисел. Приймає розмір вектора. Можна вказати межі в яких повинні бути всі елементи вектора включно та назву змінної. Наприклад vector<int> a = reader.readVectorInt(5, 1, 100, "a"); зчитає вектор з 5 елементів між 1 і 100. У строгому режимі всі значення повинні бути задані через пробіл та закінчуватися на символ кінця рядка, без зайвого пробілу після останнього символа.

  • readUInt — те саме, що й readInt, але працює з беззнаковими (невід’ємними) числами.

  • readToken — зчитує рядок. Може приймати назву змінної та регулярний вираз. Також можна задати мінімальну та максимальну довжину. Декілька прикладів:

    string s = reader.readToken(1, 1e5, "s", "(0|1)*"); — зчитує бінарний рядок (кожен символ 0 або 1), перевіряє чи його довжина між 1 і \(10^5\).

    string s = reader.readToken("s", "[a-z]+"); — зчитує рядок довільної довжини та перевіряє чи кожен символ це мала латинська буква.

    Якщо є обмеження на розмір, то їх необхідно писати як додаткові параметри функції, а не як частину регулярного виразу.

  • readLine — зчитує рядок до символу нового рядка.

  • readDouble — зчитує дійсне число. Можливі параметри: мінімальне значення, максимальне значення, мінімальна кількість цифр після коми, максимальна кількість цифр після коми, чи можна зчитувати у форматі експоненти та назва змінної. Порівняння на межі виконуються явно, тому при передачі меж враховуйте похибку дійсних чисел.

Детальніше прочитати про ці методи можна тут.

Інші важливі функції бібліотеки:

  • initValidator — повертає зчитувач в строгому режимі для перевірника. Використовувати для перевірників. Не приймає нічого.

  • initChecker — повертає масив з трьох зчитувачів у нестрогому режимі: зчитувача з потоку вхідних даних, зчитувача з потоку відповіді користувача та зчитувача з потоку відповіді автора. Використовувати для достовірників. Приймає вхідні параметри програми (int argc, char* argv[]).

  • initInteractiveChecker — повертає кортеж з таких елементів: зчитувач вхідних даних, потік для зчитування користувача (в нього потрібно виводити відповіді користувачу) та зчитувач з потоку виводу користувача. Використовувати для інтерактивних достовірників. Приймає вхідні параметри програми (int argc, char* argv[]).

  • initScorer — повертає масив з трьох зчитувачів у нестрогому режимі: зчитувача з потоку вхідних даних, зчитувача з потоку відповіді користувача та зчитувача з потоку відповіді автора. Використовувати для оцінювачів. Приймає вхідні параметри програми (int argc, char* argv[]).

  • isClose — перевіряє чи дійсні числа є близькими. Приймає два дійсних числа, абсолютну та відносну похибки. Похибки за замовчуванням рівні \(10^{-7}\).

  • equalsIgnoreCase — перевіряє чи рядки однакові, ігноруючи регістр.

  • check — приймає умову і рядок (помилку в разі невиконання умови). Якщо умова не виконується виводить рядок.

Приклади написання перевірників, достовірників та інших першоджерел можна знайти тут.

Бібліотека algotester_generator.h

Ця бібліотека створена для полегшення написання генераторів до задач. Вона містить в собі клас AlgotesterGenerator. Для роботи з нею Вам потрібно ініціалізувати генератор функцією initGenerator. Вона приймає параметри, які отримує Ваша програма при запуску. Це можна зробити так: auto gen = initGenerator(argc, argv). При створенні тестів генератором рекомендуємо завжди ставити відмітку в полі «Додавати міш до аргументів». Після цього Ви зможете використовувати методи для генерування різних величин.

Список методів класу AlgotesterGenerator та їх короткий опис:

  • randInt — повертає випадкове, рівномірно розподілене, ціле 64-бітне число. В цей метод ще можна передати межі. Якщо передати одне число \(n\), то згенероване число буде з проміжку \([0, n)\). Якщо ж передати два числа \(l\) та \(r\) — то з проміжку \([l, r]\).

  • randUInt — те саме, що й randInt, але генерує беззнакові (невід’ємні) числа.

  • randDouble — повертає випадкове, рівномірно розподілене, дійсне число з проміжку \([0, 1]\). Якщо передати одне число \(n\), то згенероване число буде з проміжку \([0, n]\). Якщо ж передати два числа \(l\) та \(r\) — то з проміжку \([l, r]\).

  • shuffle — змінює порядок елементів на випадковий. Може приймати вектор, або ітератори на початок та кінець.

  • randomElement — повертає випадковий елемент вектора.

  • randLogUniform — приймає ціле число \(n\), повертає випадкове число з проміжку \([1, n]\), таке що логарифм числа є рівномірно розподіленою величиною. Це може бути корисно, якщо Ви хочете генерувати як великі, так і малі тести.

  • randBiasedInt — приймає межі та \(t\). Якщо лише одна межа \(n\), то генерує число в проміжку \([0, n)\). Якщо ж дві межі \(l\) та \(r\), то з проміжку \([l, r]\). Генерує \(|t| + 1\) число. Якщо \(t = 0\), то повертає випадкове число, якщо \(t < 0\), то повертає найменше зі згенерованих, якщо \(t > 0\) — найбільше. Працює за O(1).

  • getArg — приймає індекс \(i\), повертає \(i\)-тий аргумент із вхідних параметрів.

Повний опис всіх методів можна знайти тут.