18 KiB
18 KiB
Структура пакета Polygon
📦 Типичная структура Polygon пакета
problem-name.zip
│
├── problem.xml ← Главный дескриптор задачи
│
├── tests/ ← Тесты для проверки решений
│ ├── 01 ← Входные данные (без расширения!)
│ ├── 01.a ← Ответы (могут отсутствовать)
│ ├── 02
│ ├── 02.a
│ └── ...
│
├── files/ ← Вспомогательные файлы
│ ├── testlib.h ← Библиотека для checker/validator/generator
│ ├── olymp.sty ← LaTeX стиль для statements
│ ├── problem.tex ← Шаблон условия
│ ├── statements.ftl ← FreeMarker шаблон
│ │
│ ├── tests/ ← Тесты для checker/validator
│ │ ├── checker-tests/
│ │ │ ├── 01
│ │ │ ├── 01.a
│ │ │ └── 01.o ← Ожидаемый output
│ │ │
│ │ └── validator-tests/
│ │ ├── 01
│ │ ├── 02
│ │ └── ...
│ │
│ ├── g.cpp ← Generator (генератор тестов)
│ ├── g.exe
│ ├── v.cpp ← Validator (валидатор входных данных)
│ ├── v.exe
│ ├── check.cpp ← Checker (проверка ответа)
│ ├── check.exe
│ ├── interactor.cpp ← Interactor (для интерактивных задач)
│ ├── interactor.exe
│ │
│ └── [resource files] ← Дополнительные ресурсы для решений
│ ├── aplusb.h ← Header для grader-задач
│ ├── grader.cpp ← Grader для компиляции с решением
│ └── main.py ← Python wrapper для grader
│
├── solutions/ ← Эталонные решения
│ ├── sol.cpp ← Главное (main) решение
│ ├── sol.exe
│ ├── sol.py
│ ├── sol.java
│ │
│ ├── sol-accepted-1.cpp ← Дополнительные AC решения
│ ├── sol-wa.cpp ← Wrong Answer решения (для теста)
│ ├── sol-tl.cpp ← Time Limit решения
│ ├── sol-ml.cpp ← Memory Limit решения
│ └── ...
│
├── statements/ ← Условия задачи
│ ├── english/
│ │ ├── problem.tex ← Исходник условия (LaTeX)
│ │ ├── problem-properties.json
│ │ ├── tutorial.tex ← Разбор задачи
│ │ ├── example.01 ← Примеры из условия (input)
│ │ └── example.01.a ← Примеры из условия (output)
│ │
│ ├── russian/
│ │ └── ...
│ │
│ ├── .html/ ← Сгенерированные HTML
│ │ ├── english/
│ │ │ ├── problem.html
│ │ │ ├── tutorial.html
│ │ │ └── problem-statement.css
│ │ └── russian/
│ │
│ └── .pdf/ ← Сгенерированные PDF
│ ├── english/
│ │ ├── problem.pdf
│ │ └── tutorial.pdf
│ └── russian/
│
├── statement-sections/ ← Секции условия (модульно)
│ ├── english/
│ │ ├── legend.tex
│ │ ├── input.tex
│ │ ├── output.tex
│ │ ├── notes.tex
│ │ ├── scoring.tex
│ │ └── examples/
│ └── russian/
│
├── materials/ ← Материалы для участников
│ ├── grader-cpp.zip ← Grader для C++
│ ├── grader-py.zip ← Grader для Python
│ └── ...
│
├── scripts/ ← Скрипты для работы с пакетом
│ ├── gen-answer.sh
│ ├── gen-input-via-files.sh
│ ├── run-validator-tests.sh
│ └── ...
│
├── check.cpp ← Checker в корне (копия)
├── check.exe
├── doall.sh ← Скрипт сборки всего
├── doall.bat
├── wipe.sh ← Скрипт очистки
├── wipe.bat
└── tags ← Теги задачи (metadata)
📄 Основные файлы и их назначение
1. problem.xml (обязательный)
Центральный дескриптор задачи:
<?xml version="1.0" encoding="utf-8"?>
<problem revision="17" short-name="example-problem" url="...">
<names>
<name language="english" value="Problem Title"/>
</names>
<judging>
<testset name="tests">
<time-limit>2000</time-limit> <!-- мс -->
<memory-limit>268435456</memory-limit> <!-- байты = 256 MB -->
<test-count>51</test-count>
<input-path-pattern>tests/%02d</input-path-pattern>
<answer-path-pattern>tests/%02d.a</answer-path-pattern>
<tests>
<test method="manual" sample="true"/> <!-- ручной, в примерах -->
<test cmd="gen 100" method="generated"/> <!-- сгенерированный -->
<test cmd="gen 1000" method="generated"/>
...
</tests>
</testset>
</judging>
<assets>
<checker name="std::ncmp.cpp" type="testlib">
<source path="files/check.cpp" type="cpp.g++17"/>
<binary path="check.exe" type="exe.win32"/>
</checker>
<validators>
<validator>
<source path="files/v.cpp" type="cpp.g++17"/>
<binary path="files/v.exe" type="exe.win32"/>
</validator>
</validators>
<solutions>
<solution tag="main">
<source path="solutions/sol.cpp" type="cpp.g++17"/>
<binary path="solutions/sol.exe" type="exe.win32"/>
</solution>
<solution tag="accepted">
<source path="solutions/sol.py" type="python.3"/>
</solution>
<solution tag="wrong-answer">
<source path="solutions/sol-wa.cpp" type="cpp.g++17"/>
</solution>
</solutions>
</assets>
</problem>
2. testlib.h (стандартная библиотека)
Библиотека от MikeMirzayanov для написания:
- Checkers - проверка правильности ответа
- Validators - проверка корректности входных данных
- Generators - генерация тестов
- Interactors - интерактивное взаимодействие
Основные функции:
#include "testlib.h"
// Checker
int main(int argc, char* argv[]) {
registerTestlibCmd(argc, argv);
int jans = ans.readInt(); // Правильный ответ
int pans = ouf.readInt(); // Ответ участника
if (jans == pans)
quitf(_ok, "Correct");
else
quitf(_wa, "Wrong answer: %d instead of %d", pans, jans);
}
// Validator
int main(int argc, char* argv[]) {
registerValidation(argc, argv);
int n = inf.readInt(1, 100000, "n");
inf.readEoln();
inf.readEof();
}
// Generator
int main(int argc, char* argv[]) {
registerGen(argc, argv, 1);
int n = opt<int>("n");
println(n);
for (int i = 0; i < n; i++)
println(rnd.next(1, 1000000));
}
3. Тесты (tests/)
Формат:
tests/01 ← Входные данные (plain text, без расширения)
tests/01.a ← Ответ (answer file)
Пример:
# tests/01 (input)
2 3
# tests/01.a (answer)
5
Метаданные из problem.xml:
<tests>
<test method="manual" sample="true"/> <!-- tests/01 - вручную, в примерах -->
<test cmd="gen 10 5" method="generated"/> <!-- tests/02 - сгенерирован -->
<test cmd="gen 100 50" method="generated"/> <!-- tests/03 -->
</tests>
4. Generator (g.cpp)
Программа для генерации тестов:
#include "testlib.h"
#include <iostream>
int main(int argc, char* argv[]) {
registerGen(argc, argv, 1);
int n = opt<int>(1); // Первый аргумент
int maxVal = opt<int>(2); // Второй аргумент
std::cout << n << std::endl;
for (int i = 0; i < n; i++) {
std::cout << rnd.next(1, maxVal);
if (i + 1 < n) std::cout << " ";
}
std::cout << std::endl;
return 0;
}
Использование:
# В problem.xml указано:
<test cmd="gen 1000 10000" method="generated"/>
# Polygon запускает:
g.exe 1000 10000 > tests/05
5. Checker (check.cpp)
Программа для проверки корректности ответа.
Типы checkers:
A. Стандартные (встроенные в testlib.h):
std::ncmp.cpp // Сравнение одного целого числа
std::fcmp.cpp // Сравнение одного float с точностью
std::wcmp.cpp // Сравнение по словам (tokens)
std::lcmp.cpp // Построчное сравнение
std::nyesno.cpp // Проверка YES/NO
B. Custom checker:
#include "testlib.h"
int main(int argc, char* argv[]) {
registerTestlibCmd(argc, argv);
// inf - входной файл (input)
// ouf - output участника (output user file)
// ans - правильный ответ (answer)
int n = inf.readInt();
std::vector<int> jans(n);
for (int i = 0; i < n; i++)
jans[i] = ans.readInt();
std::vector<int> pans(n);
for (int i = 0; i < n; i++)
pans[i] = ouf.readInt();
// Проверка: порядок не важен (множества равны)
std::sort(jans.begin(), jans.end());
std::sort(pans.begin(), pans.end());
if (jans == pans)
quitf(_ok, "Correct");
else
quitf(_wa, "Wrong answer");
}
Exit codes:
0- OK (правильный ответ) ✅1- WA (неправильный ответ) ❌2- PE (presentation error)3- FAIL (ошибка в самом чекере)7- Partial (частичный балл, для IOI-style)
6. Validator (v.cpp)
Проверяет корректность входных данных:
#include "testlib.h"
int main(int argc, char* argv[]) {
registerValidation(argc, argv);
// Проверка формата входных данных
int n = inf.readInt(1, 100000, "n"); // 1 ≤ n ≤ 100000
inf.readEoln(); // Конец строки
for (int i = 0; i < n; i++) {
inf.readInt(1, 1000000000, "a[i]");
if (i + 1 < n) inf.readSpace();
else inf.readEoln();
}
inf.readEof(); // Конец файла
return 0;
}
Назначение:
- Проверка ограничений (1 ≤ n ≤ 10⁶)
- Проверка формата (пробелы, переводы строк)
- Валидация структуры (дерево, граф и т.д.)
7. Interactor (для интерактивных задач)
Посредник между решением и тестирующей системой:
#include "testlib.h"
int main(int argc, char* argv[]) {
registerInteraction(argc, argv);
int n = inf.readInt(); // Загаданное число
int queries = 0;
while (queries < 20) {
int guess = ouf.readInt(1, 1000000); // Запрос участника
queries++;
if (guess == n) {
tout << "YES" << endl;
quitf(_ok, "Found in %d queries", queries);
} else if (guess < n) {
tout << ">" << endl; // Больше
} else {
tout << "<" << endl; // Меньше
}
}
quitf(_wa, "Too many queries");
}
Streams в interactor:
inf- входной файл (input)ouf- output участника (чтение запросов)tout- передача данных участнику (ответы на запросы)ans- правильный ответ (не используется в интерактивных)
8. Solutions (эталонные решения)
Типы решений:
<solution tag="main"> <!-- Главное решение (генерирует .a файлы) -->
<solution tag="accepted"> <!-- Дополнительные AC решения -->
<solution tag="wrong-answer"> <!-- WA (для теста checker'а) -->
<solution tag="time-limit-exceeded"> <!-- TL -->
<solution tag="memory-limit-exceeded"> <!-- ML -->
<solution tag="rejected"> <!-- Другие RE/PE -->
Назначение:
main- используется для генерации answer filesaccepted- проверка, что задача решаема разными способамиwrong-answer- тестирование checker'аtime-limit-exceeded- проверка TL
9. Grader-задачи (специальный тип)
Участник пишет функцию, а не всю программу.
Структура:
files/
├── aplusb.h ← Header с сигнатурой функции
├── grader.cpp ← Main + вызов функции участника
└── main.py ← Python wrapper
solutions/
└── sol.cpp ← Реализация функции (не main!)
Пример:
// aplusb.h
int sum(int a, int b);
// grader.cpp
#include "aplusb.h"
#include <iostream>
int main() {
int a, b;
std::cin >> a >> b;
std::cout << sum(a, b) << std::endl;
return 0;
}
// sol.cpp (решение участника)
#include "aplusb.h"
int sum(int a, int b) {
return a + b;
}
📊 Статистика по примерам пакетов
a-plus-b-graders-7.zip:
Размер: 2.4 MB
Файлов: ~50
Структура:
✅ problem.xml
✅ tests/ (8 тестов: 01-08, без .a файлов)
✅ files/testlib.h
✅ files/aplusb.h (grader header)
✅ files/grader.cpp
✅ files/g.cpp, g.exe (generator)
✅ files/v.cpp, v.exe (validator)
✅ check.cpp, check.exe (ncmp - числовой checker)
✅ solutions/sol.cpp (main)
✅ solutions/sol.py (accepted)
✅ statements/english/ (условие)
example-interactive-binary-search-26.zip:
Размер: 10.7 MB
Файлов: ~100+
Структура:
✅ problem.xml
✅ tests/ (21 тест: 01-21, без .a файлов)
✅ files/testlib.h
✅ files/interactor.cpp, interactor.exe ← ИНТЕРАКТИВНАЯ!
✅ files/gen.cpp, gen.exe
✅ files/val.cpp, val.exe
✅ check.cpp, check.exe
✅ solutions/ (16 решений: main, ac, wa, tl, ml, pe, ...)
✅ statements/english/ + russian/
exam-queue-17.zip:
Размер: 6.6 MB
Файлов: ~80
Структура:
✅ problem.xml
✅ tests/ (51 тест: 01-51, без .a файлов)
✅ files/testlib.h
✅ files/gen.cpp, gen.exe
✅ files/val.cpp, val.exe
✅ check.cpp, check.exe
✅ solutions/ (множество решений)
✅ statements/russian/ (только русское условие)
💡 Ключевые выводы
Обязательные компоненты:
- ✅
problem.xml- дескриптор - ✅
tests/- тесты - ✅
files/testlib.h- библиотека - ✅
solutions/- хотя бы одно main решение
Опциональные (но часто присутствуют):
check.cpp- custom checker (иначе используется wcmp)v.cpp- validatorg.cpp- generatorinteractor.cpp- для интерактивных задачstatements/- условия на разных языках*.aфайлы - ответы (генерируются из main solution)
Особенности формата:
- Входные файлы БЕЗ расширения (01, 02, не 01.in!)
- Ответы с расширением
.a(01.a, 02.a) - testlib.h - единая библиотека для всего
- problem.xml - полное описание всего пакета
🔗 Полезные ссылки
- Polygon: https://polygon.codeforces.com/
- testlib.h GitHub: https://github.com/MikeMirzayanov/testlib
- Документация testlib: https://codeforces.com/testlib
- Tutorial по Polygon: https://codeforces.com/blog/entry/101072
🎯 Поддержка в LiquidCode.Tester
Наша система полностью поддерживает:
- ✅ Парсинг problem.xml
- ✅ Тесты в формате tests/01, tests/01.a
- ✅ Автоматическую генерацию answer файлов из main solution
- ✅ Компиляцию и запуск custom checkers (testlib-based)
- ✅ Определение лимитов времени/памяти из problem.xml
- ✅ Поддержку всех основных языков (C++, Java, Python, C#, Kotlin)
В разработке:
- ⏳ Поддержка interactor для интерактивных задач
- ⏳ Поддержка grader-задач
- ⏳ Запуск validator для проверки входных данных