Codenrock
В разработке
В разработке
ОрганизаторПродвинутый15 мин

Настройка CODING-задач

Полное руководство по созданию и настройке задач на программирование

Настройка CODING-задач

CODING — это тип задач для алгоритмических соревнований. Участники пишут код, который автоматически проверяется на наборе тестов. В этом руководстве — всё о создании и настройке таких задач.


Обзор

Как работает проверка

1. Участник отправляет код
2. Код компилируется (для C++, Java, и т.д.)
3. Программа запускается на каждом тесте
4. Вывод сравнивается с ожидаемым (через чеккер)
5. Результаты возвращаются участнику

Компоненты CODING-задачи

КомпонентОписаниеОбязательно
УсловиеТекст задачи с описаниемДа
ТестыПары вход/выходДа
ОграниченияВремя и памятьДа
ЯзыкиРазрешённые языки программированияДа
ЧеккерПрограмма для проверки ответаНет (стандартный)
ИнтеракторДля интерактивных задачНет

Создание CODING-задачи

Шаг 1: Создайте задачу

  1. Перейдите в «Треки» → выберите трек
  2. Нажмите «Управление задачами»
  3. Нажмите «+ Добавить задачу»
  4. Выберите тип CODING

Шаг 2: Заполните основные поля

ПолеОписаниеПример
НазваниеНазвание задачи«Сумма чисел»
УсловиеОписание задачи (Markdown)Полный текст условия
БаллыМаксимальный балл за задачу100
ПорядокПозиция в треке1

Шаг 3: Настройте ограничения

НастройкаОписаниеРекомендации
Время (мс)Лимит времени на один тест1000-5000 мс
Память (МБ)Лимит памяти256-512 МБ

Важно: Ограничения применяются к каждому тесту отдельно. Если тестов 10 и лимит 1 сек, общее время может быть до 10 секунд.

Шаг 4: Выберите языки

  1. В разделе «Языки программирования» выберите доступные языки
  2. Укажите язык по умолчанию (будет выбран при открытии)
  3. Опционально: отключите выбор языка (если разрешён только один)

Шаг 5: Добавьте тесты

Подробнее в разделе Тесты ниже.

Шаг 6: Сохраните задачу

Нажмите «Создать» или «Сохранить».


Ограничения по времени и памяти

Как вычисляются ограничения

ПараметрОписание
ВремяВремя CPU, не реальное время. Включает только выполнение кода пользователя
ПамятьПиковое использование памяти процессом (heap + stack)

Рекомендации по настройке

Тип задачиВремяПамятьКомментарий
Простая1 сек256 МБЛинейные алгоритмы
Средняя2-3 сек256 МБO(N log N) алгоритмы
Сложная5 сек512 МБТяжёлые вычисления
Строки2-3 сек512 МБРабота с большими строками

Учёт особенностей языков

Разные языки имеют разную скорость выполнения:

ЯзыкОтносительная скоростьРекомендация
C/C++1x (базовая)Эталон для расчёта лимитов
Java2-3x медленнееУвеличьте лимит в 2-3 раза
Python10-50x медленнееУвеличьте лимит в 10+ раз
JavaScript3-5x медленнееУвеличьте лимит в 3-5 раз

Совет: Если задача рассчитана на C++, но разрешён Python, установите более мягкий лимит или используйте разные лимиты для разных языков.


Тесты

Структура теста

Каждый тест состоит из:

КомпонентОписание
Входные данные (input)Что получает программа на stdin
Ожидаемый вывод (output)Что должна вывести программа
БаллыОчки за этот тест (опционально)

Публичные vs скрытые тесты

ТипВидны участникуНазначение
ПубличныеВход и выходПримеры в условии
СкрытыеТолько результатОсновная проверка

Добавление тестов

Вручную

  1. В редакторе задачи перейдите в раздел «Тесты»
  2. Нажмите «+ Добавить тест»
  3. Заполните:
    • Входные данные — текст или загрузите файл
    • Ожидаемый вывод — текст или загрузите файл
    • Публичный — поставьте галочку для примеров
    • Баллы — если включён режим частичных баллов

Из файлов

Для большого количества тестов:

  1. Подготовьте файлы с именами:
    01.in, 01.out
    02.in, 02.out
    ...
    
  2. Заархивируйте в ZIP
  3. Загрузите через «Импорт тестов»

Рекомендации по тестам

КатегорияОписаниеПример
Граничные случаиМинимальные/максимальные значенияN=1, N=10^9
Особые случаиНули, отрицательные, пустыеN=0, arr=[]
СлучайныеСредние случайные данныеСгенерированные
МаксимальныеСтресс-тесты на производительностьМаксимальный N

Генерация тестов

Для автоматической генерации используйте скрипт:

import random

def generate_test(test_num, n_min, n_max):
    n = random.randint(n_min, n_max)
    arr = [random.randint(1, 10**9) for _ in range(n)]

    # Входные данные
    with open(f'{test_num:02d}.in', 'w') as f:
        f.write(f'{n}\n')
        f.write(' '.join(map(str, arr)) + '\n')

    # Ожидаемый вывод (ваш эталонный алгоритм)
    result = solve(n, arr)
    with open(f'{test_num:02d}.out', 'w') as f:
        f.write(f'{result}\n')

# Генерация 20 тестов
for i in range(1, 21):
    generate_test(i, 1, 10**5)

Чеккер (Checker)

Что такое чеккер

Чеккер — это программа, которая проверяет правильность ответа участника. Стандартный чеккер просто сравнивает вывод участника с ожидаемым выводом.

Когда нужен кастомный чеккер

СитуацияПример
Несколько правильных ответов«Найдите любое решение уравнения»
Точность вычислений«Ответ с точностью до 10^-6»
Порядок не важен«Выведите множество чисел»
Частичные баллы«Чем ближе к оптимуму, тем больше баллов»

Стандартный чеккер

Если кастомный чеккер не указан, используется стандартный:

  1. Разбивает вывод на токены (слова)
  2. Сравнивает токены по порядку
  3. Игнорирует лишние пробелы и переносы строк
  4. Результат: OK (всё совпало) или WA (не совпало)

Формат кастомного чеккера

Чеккер — это исполняемый файл, который получает:

АргументОписание
argv[1]Путь к файлу с входными данными (input)
argv[2]Путь к файлу с выводом участника (output)
argv[3]Путь к файлу с ожидаемым ответом (answer)

Чеккер возвращает:

Exit codeЗначение
0Accepted (ответ правильный)
1Wrong Answer (ответ неправильный)
2Presentation Error (неверный формат)

Пример чеккера на C++

#include <iostream>
#include <fstream>
#include <cmath>

int main(int argc, char* argv[]) {
    std::ifstream input(argv[1]);   // входные данные
    std::ifstream output(argv[2]);  // ответ участника
    std::ifstream answer(argv[3]);  // ожидаемый ответ

    double expected, actual;
    answer >> expected;

    if (!(output >> actual)) {
        std::cerr << "Ошибка чтения ответа участника" << std::endl;
        return 1; // WA
    }

    // Проверка с точностью 10^-6
    if (std::abs(expected - actual) < 1e-6) {
        std::cout << "OK" << std::endl;
        return 0; // AC
    } else {
        std::cerr << "Expected: " << expected << ", Got: " << actual << std::endl;
        return 1; // WA
    }
}

Пример чеккера на Python

#!/usr/bin/env python3
import sys

def main():
    input_file = sys.argv[1]   # входные данные
    output_file = sys.argv[2]  # ответ участника
    answer_file = sys.argv[3]  # ожидаемый ответ

    with open(answer_file) as f:
        expected = float(f.read().strip())

    try:
        with open(output_file) as f:
            actual = float(f.read().strip())
    except:
        print("Ошибка чтения ответа", file=sys.stderr)
        sys.exit(1)  # WA

    # Проверка с точностью 10^-6
    if abs(expected - actual) < 1e-6:
        print("OK")
        sys.exit(0)  # AC
    else:
        print(f"Expected: {expected}, Got: {actual}", file=sys.stderr)
        sys.exit(1)  # WA

if __name__ == "__main__":
    main()

Чеккер с частичными баллами

Для задач, где нужно начислять частичные баллы:

  1. Включите опцию «Score from Checker» в настройках
  2. Чеккер должен выводить score в stdout
  3. Выберите метод агрегации (SUM, AVG, MIN, MAX)
// Чеккер выводит score от 0 до 100
int main(int argc, char* argv[]) {
    // ... проверка ...

    double accuracy = calculateAccuracy(expected, actual);
    int score = static_cast<int>(accuracy * 100);

    std::cout << score << std::endl;  // Выводим score
    return 0;  // Всегда возвращаем 0
}

Загрузка чеккера

  1. В настройках задачи найдите раздел «Чеккер»
  2. Загрузите скомпилированный бинарный файл или скрипт
  3. Убедитесь, что файл исполняемый

Важно: Чеккер должен быть скомпилирован для Linux x64 (Alpine/Debian).

Где взять чеккеры

ИсточникОписание
testlib.hБиблиотека от Codeforces для написания чеккеров
PolygonСистема подготовки задач с готовыми чеккерами
GitHubРепозитории с примерами чеккеров

Пример с testlib.h:

#include "testlib.h"

int main(int argc, char* argv[]) {
    registerTestlibCmd(argc, argv);

    double expected = ans.readDouble();
    double actual = ouf.readDouble();

    if (std::abs(expected - actual) < 1e-6) {
        quitf(_ok, "Correct: %.6f", actual);
    } else {
        quitf(_wa, "Expected: %.6f, got: %.6f", expected, actual);
    }
}

Интерактор (Interactor)

Что такое интерактор

Интерактор — программа для интерактивных задач, где решение участника общается с системой в режиме диалога (вопрос-ответ).

Когда нужен интерактор

Тип задачиПример
Угадывание«Угадай число за минимум вопросов»
Игры«Сыграй оптимально против бота»
Запросы«Узнай структуру графа через запросы»

Как работает интерактор

┌─────────────┐     stdin      ┌──────────────┐
│  Интерактор │  ──────────▶   │   Решение    │
│             │  ◀──────────   │  участника   │
└─────────────┘     stdout     └──────────────┘
  1. Интерактор отправляет данные на stdin решения
  2. Решение читает stdin и отвечает в stdout
  3. Интерактор читает stdout решения и отвечает
  4. Диалог продолжается до завершения

Формат интерактора

Интерактор получает:

АргументОписание
argv[1]Путь к файлу с входными данными (секретные данные)
argv[2]Путь к файлу с ответом (для записи результата)
stdinВывод решения участника
stdoutВвод для решения участника

Пример интерактора

Задача: угадать число от 1 до N за минимум вопросов.

#include <iostream>
#include <fstream>

int main(int argc, char* argv[]) {
    std::ifstream input(argv[1]);  // секретное число
    std::ofstream answer(argv[2]); // результат

    int secret, n;
    input >> n >> secret;

    std::cout << n << std::endl;  // Сообщаем N участнику
    std::cout.flush();

    int queries = 0;
    std::string command;
    int guess;

    while (std::cin >> command >> guess) {
        queries++;

        if (command == "?") {  // Вопрос: "число >= guess?"
            if (guess <= secret) {
                std::cout << "YES" << std::endl;
            } else {
                std::cout << "NO" << std::endl;
            }
            std::cout.flush();
        } else if (command == "!") {  // Ответ
            if (guess == secret) {
                answer << "OK " << queries << std::endl;
                return 0;  // AC
            } else {
                answer << "WA: expected " << secret << ", got " << guess << std::endl;
                return 1;  // WA
            }
        }

        if (queries > 100) {  // Лимит вопросов
            answer << "WA: too many queries" << std::endl;
            return 1;
        }
    }

    answer << "WA: unexpected end of output" << std::endl;
    return 1;
}

Важные моменты

  1. flush: После каждого вывода делайте std::cout.flush() или std::endl
  2. Лимиты: Ограничивайте количество запросов
  3. Протокол: Чётко опишите протокол в условии задачи

Загрузка интерактора

  1. В настройках задачи найдите раздел «Интерактор»
  2. Загрузите скомпилированный бинарный файл
  3. Создайте тесты с секретными данными

Режимы оценивания

Стандартный режим

Все тесты пройдены = полные баллы, иначе = 0.

Настройка: По умолчанию, ничего не нужно включать.

Частичные баллы за тесты

Баллы пропорционально пройденным тестам.

Настройка:

  1. Укажите баллы для каждого теста
  2. Общий балл = сумма баллов за пройденные тесты

Score from Checker

Баллы определяет чеккер.

Настройка:

  1. Включите «Score from Checker»
  2. Выберите метод агрегации:
    • SUM: Сумма score по всем тестам
    • AVG: Среднее значение
    • MIN: Минимальный score
    • MAX: Максимальный score (по умолчанию)
  3. Загрузите чеккер, который выводит score

Best Score Mode

Учитывается лучший результат из всех отправок.

Настройка: Включите «Best Score Mode»

Поведение:

  • При Submit сравнивается с текущим сохранённым результатом
  • Сохраняется только если новый результат лучше
  • Участник не может ухудшить свой результат

Языки программирования

Управление языками

  1. В настройках задачи перейдите в «Языки»
  2. Выберите разрешённые языки из списка
  3. Укажите язык по умолчанию

Доступные языки

ЯзыкВерсия
Python3.11
C++C++17
Java17
JavaScriptNode.js 18
Go1.21
Rust1.70
C#.NET 7

Шаблон кода по умолчанию

Для каждого языка можно задать шаблон, который будет показан участнику при открытии редактора:

# Python шаблон
def solve():
    n = int(input())
    # Ваш код здесь
    pass

if __name__ == "__main__":
    solve()

Ограничение на один язык

Если задача только на одном языке:

  1. Выберите только один язык
  2. Отключите «Разрешить выбор языка»

Лимиты отправок

Настройка лимитов

ПараметрОписание
maxSolutionsCountМаксимальное количество отправок
solutionsCountPeriodПериод: DAILY (в сутки) или ALL_TIME (за всё время)

Примеры

НастройкаОписание
50 / ALL_TIME50 отправок на всё соревнование
10 / DAILY10 отправок в сутки (сбрасывается в полночь)
nullБез ограничений

Когда использовать

СитуацияРекомендация
Обычное соревнованиеБез ограничений или 50-100 за всё время
Тест на знания3-5 попыток за всё время
ML/оптимизация10-20 в сутки

Чек-лист создания задачи

  • Условие написано понятно
  • Формат ввода/вывода описан чётко
  • Ограничения указаны (время, память, диапазоны)
  • Публичные тесты соответствуют примерам в условии
  • Скрытые тесты покрывают граничные случаи
  • Ограничения реалистичны для выбранных языков
  • Эталонное решение проходит все тесты
  • Кастомный чеккер протестирован (если используется)
  • Интерактор протестирован (если используется)

Частые вопросы

В: Как добавить задачу с несколькими правильными ответами?

О: Используйте кастомный чеккер, который проверяет, что ответ удовлетворяет условиям, а не сравнивает с эталоном.

В: Как сделать разные лимиты для разных языков?

О: В текущей версии лимиты одинаковые для всех языков. Установите лимит, достаточный для самого медленного языка.

В: Можно ли добавить тесты после публикации?

О: Да, но это может повлиять на уже сданные решения. Рекомендуется добавлять тесты до начала соревнования.

В: Где взять testlib.h?

О: Скачайте с GitHub: https://github.com/MikeMirzayanov/testlib

В: Как протестировать чеккер локально?

О:

./checker input.txt output.txt answer.txt
echo $?  # 0 = AC, 1 = WA

В: Почему участники получают TLE на Python, но AC на C++?

О: Python в 10-50 раз медленнее C++. Увеличьте лимит времени или укажите, что задача рассчитана на C++.


Связанные статьи

Последнее обновление: 07.02.2026
К оглавлению