Блог пользователя MikeMirzayanov

Автор MikeMirzayanov, 13 лет назад, По-русски

Библиотека testlib.h

Здесь пойдет речь о библиотеке testlib.h, которая была написана мной достаточно давно — году в 2005-ом. Незадолго до этого было объявлено об отказе на финале ACM-ICPC от использования Pascal, популярность набирал TopCoder (где так же нет Pascal/Delphi). Все это приводило к мыслям, что писать чекеры на Pascal вечно невозможно, да и не всегда достаточно удобно, да и кроссплатформенным этот вариант назвать трудно — по-моему далеко не все testlib.pas (которых несколько разновидностей) компилируются free pascal.

Про чекеры

Так как не все читатели являются авторами задач, то давайте проясним смысл этого слова. Чекером называется программа, которая читает входной файл (тест), вывод проверяемой программы, предполагаемый ответ и выводит вердикт относительно корректности вывода проверяемой программы. Обычно, бывают следующие вердикты: OK (ответ верен, представлен один из правильных ответов), WA (ответ неверен), PE (формат вывода не верен, я этот вердикт не люблю), FL (произошел epic fail — например, чекер выяснил, что решение участника вывело более оптимальный ответ, чем авторское решение). Конечно, при тестировании подготовленных задач не должен появляться FL, но о нем мы расскажем чуть позже.

Конечно, в большинстве задач не требуется "интеллектуальный" чекер, так как условие задачи однозначно определяет вывод участника. Более того, на многих соревнованиях по техническим причинам (TopCoder) или в силу традиций (большое количество ACM-ICPC regionals) это стало правилом. С другой стороны, даже при однозначном выводе могут быть тонкости — на сколько позволять участникам не соблюдать формат. Возможны следующие моменты (и не только они):

  • вывод перевода строки или его отсутствие в конце последней строки файла;
  • вывод лишних пробелов, особенно в задачах со всякими "Case: 12" или завершающий пробел в конце последовательности чисел;
  • вывод вещественных чисел — вообще, отдельная песня, так как надо определяться сколько нужно знаков (ровно столько? не меньше?), да и округлиться 0.34999999 может как угодно.

Все это приводит к заключению, что даже в задачах с однозначным выводом проверка вывода дело тонкое. Обычно, если в условии задачи не написано четко про пробелы, то следует допускать их произвольное расположение в выводе. Лояльность относительно заключительного перевода строки тоже, я думаю, правило хорошего тона. Так как в разных задачах оказывается, что требуется немного разное "точное" сравнение, то и в таких задачах применяют чекеры, просто их не пишут каждый раз, а используют готовые (написанные заранее).

Обычно, чекер компилируется в исполняемый файл, который принимает три (опционально два) аргумента командной строки: входной-файл, файл-вывода, файл-ответа. В англоязычной терминологии это input, output и answer. Возвращает значение чекер обычно через exit-codes выполняемого процесса. За исключением ejudge тестирующие системы обычно используют:

  • код возврата 0 для обозначения OK;
  • код возврата 1 для обозначения WA;
  • код возврата 2 для обозначения PE;
  • код возврата 3 для обозначения FL.

Что очень важно хороший чекер выведет в stdout вердикт и его причину в виде короткой фразы на английском языке (иногда для русскоязычных школьных соревнований используется русский язык). Стоит помнить, что вывод должен быть информативен и не очень громоздким. Примеры хороших выводов: "ok n=10, m=13, answer=34", "ok No solution", "wrong answer Expected -1, found 4294967295". Примеры плохих выводов "ok OK", "wrong answer Palevo!".

Чекеры и testlib.h

Писать чекеры — с одной стороны просто, с другой стороны в этом много подводных камней. Что может быть проще написать программу для сравнивания двух целых чисел? Однако вдруг оказывается, что scanf("%d", &a) (да и многие другие стандартные способы считать целое число во многих языках) при считывании 4294967295 не просигнализирует об ошибке, и будет уверен, что прочел -1. Отделить PE и WA при чтении целого числа тоже отдельная задачка.

По этой причине еще в лохматые 90-е Антоном Сухановым и Романом Елизаровым на был написан testlib для Pascal, который верой и правдой служил на многих NEERC и в модифицированном виде активно используется до сих пор. Иногда возникают проблемы обратной несовместимости версий этой библиотеки или около того (модуль symbols). Заметим, что эта библиотека была переписана Андреем Лопатиным и Николаем Дуровым и другой вариант активно используется на многих контестах СпбГУ и по сей день. На сколько я понимаю, библиотеки эти не совсем совместимы.

Библиотека testlib.h была написана мной в 2005-м году по образу и подобию тестлибов для Pascal. Это позволило упростить переход на нее тем многим, кто уже успел поработать с testlib.pas. Достаточно быстро testlib.h стал использоваться не только на саратовских соревнованиях. Одним из первых широкомасштабных использований стала Всероссийская олимпиада школьников года примерно 2006-го. С тех пор, testlib.h стал де-факто стандартом для написания чекеров на С++ и применяется на совсем разных контестах.

Приведем пример простейшего чекера на testlib.h, который сравнивает answer и output, ожидая в каждом из них по одному 32-х битному целому числу.

#include "testlib.h"

int main(int argc, char * argv[])
{
   setName("compare two signed int32 numbers");
   registerTestlibCmd(argc, argv);

   int ja = ans.readInt();
   int pa = ouf.readInt();

   if (ja != pa)
       quitf(_wa, "expected %d, found %d", ja, pa);

   quitf(_ok, "answer is %d", ja);
}

Я думаю код достаточно понятен. Отмечу, что программе доступны три потока inf, ouf, ans — потоки входных, выходных данных и поток с ответом. Для потоков есть удобные функции чтения, которые позволяют читать разнообразные данные. Ошибки чтения трактуются по разному для разных потоков. Например, если невозможно прочитать число с помощью ouf.readInt(), то будет PE, но если использовался inf.readInt() или ans.readInt() то будет FL. Об этом не надо особенно задумываться при разработке — здесь все вполне логично и естественно. Еще немного примеров (подразумевается чтение из ouf, для inf и ans в случае ошибок будут FL).

  • readInt(1, 100, "n") — попытается прочесть целое от 1 до 100, вернет WA (для версий 0.7+, иначе PE) если число не в заданных границах. Текст вывода будет примерно таким: Integer n violates the range [1, 100].
  • readInt(1, 100) — тоже самое, но вывод об ошибке немного другой (без указания имени переменной).
  • readLong() — читает знаковое 64-х битное число.
  • readToken() — читает очередной токен (последовательность непробельных символов), пропускает если надо все whitespaces перед чтением токена.
  • readWord() — тоже самое, что и readToken().
  • readWord("[a-z]{1,100}") — читает токен и удостоверяется, что это последовательность малых латинских букв длины от 1 до 100, вернет WA (для версий 0.7+, иначе PE) если токен не соответствует паттерну.
  • seekEof() — пропускает все whitespaces и возвращает true если больше ничего нет в потоке.
  • readLine() — читает текущую строку до конца.

Это далеко не все возможности, следует посмотреть testlib.h (строки около 950) чтобы ознакомиться со списком всех возможностей.

Задачи с сертификатом, чекеры

Особо следует отметить такие задачи, в которых требуется сертификат. Так обычно называют вывод не только значения оптимального ответа (например длины наидлиннейшей возрастающей подпоследовательности), но и самой подпоследовательности (например, в виде индексов). Для таких задач существует определенный паттерн написания чекера. Основная часть чекера должна выглядеть как-то так:

    n = inf.readInt();

    int ja = readAnswer(ans, _fail, _fail);
    int pa = readAnswer(ouf, _wa, _pe);

    if (ja < pa)
        quitf(_wa, "Jury has better answer: %d < %d", ja, pa);

    if (ja > pa)
        quitf(_fail, "Participant has better answer: %d < %d", pa, ja);

    quitf(_ok, "n=%d, m=%d, result=%d", n, m, ja);

Здесь функция readAnswer читает ответ (вывод) из заданного потока, удостоверяется в его корректности и возвращает значение целевой функции оптимизации. Второй и третий параметры функции нужны для того, чтобы использовать их в функции quitf(), это обеспечит FL на ошибках потока ответа и WA/PE на ошибках потока вывода.

Как написать чекер

Приведу список шагов по написанию чекера.

  1. Если у вас нет неоднозначности в выводе в задаче, то используйте один из стандартных чекеров. Не бойтесь быть слишком лояльными — пусть лучше ваш чекер игнорирует какие-нибудь лишние пробелы, чем будет слишком строг и испортит участникам контест.
  2. Если в задаче предполагается вывод сертификата, то пишите чекер в соответствии с паттерном в предыдущем разделе. Всегда стоит рассмотреть возможность изменения задачи, чтобы она требовала вывод сертификата. Обычно это делает задачу чуть более программистской, что неплохо.
  3. Когда пишите чекер, то учтите, что он будет компилироваться на произвольной платформе. В частности, не используйте %I64d/%lld. В testlib.h есть функция vtos(value), которая возвращает строковое представление аргумента value.
  4. Старайтесь писать максимально надежно. Есть вероятность переполнения — пишите все в long long, и так далее.
  5. Старайтесь писать все просто и прямо. Не используйте хитрый и неочевидный код.
  6. Перепрочтите условие задачи и обратите внимание на то, что вы проверяете все требования, изложенные в задаче.
  7. Будьте аккуратны с WA/PE. Например, если в задаче требуют вывести число или "No solution", то вывод "No solution", не должен приводить к PE.
  8. Убедиться, что при любом выводе участника чекер не выведет сверхдлинный комментарий. Например, выводя строки их лучше оборачивать в __testlib_part(s). Стандартные чекеры делают именно так, можно почитать их код для уточнения деталей.
  9. Тщательно потестируйте ваш чекер на предмет его адекватной работы в каждом из возможных вариантов исхода.

Пожалуй все. Пишите в комментариях замечания и предложения. Наверняка, я что-то забыл/упустил.
MikeMirzayanov

P.S. Немного ссылок:

  1. Официальный сайт testlib.h
  2. Issue (bug) tracker для testlib.h
  3. testlib.pas by SPb IFMO CTD Development Team

  • Проголосовать: нравится
  • +19
  • Проголосовать: не нравится

13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

У меня периодически гуляют мысли переписать тестлиб на питоне, но поскольку я проведением олимпиад напрямую не занимаюсь, то до дела это так и не дошло.

Интересно, кто-нибудь пытался сделать что-то подобное? Ведь, по-моему, питон отлично подходит как раз для чекеров. Я не говорю про задачи где чекер сложнее решения, но для остальных-то 90%.

  • 13 лет назад, # ^ |
      Проголосовать: нравится +1 Проголосовать: не нравится
    Дело вкуса. Я на Питоне почти не писал, так что писать чекеры на нем не захочу. Меня беспокоит слабая обратная совместимость - как можно будет использовать ваши чекеры лет через 5? Кстати, в 50% случаев хватает стандартных чекеров. А вот на Java я чекеры не люблю, так как запускаются долго, с Питоном вроде получше в этом смысле.
    • 13 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

      Ну, эти 50% я вообще не считал)

      На тему обратной совместимости я, честно говоря, не думал, но, в принципе, у питона с ней все не так и плохо. Внутри одной версии языка она в общем-то сохраняется, а новые выходят не так и часто и, например, 2 в 3 есть конвертер.

      Хотя, у всего, конечно, есть свои минусы. Зато у него лучше обстоят дела с кроссплатформенностью чем у тех же паскаля и плюсов.

      • 13 лет назад, # ^ |
          Проголосовать: нравится +1 Проголосовать: не нравится
        Я пробовал этот конвертер - не знаю как чекеры, а решения с контестов он не в состоянии конвертить.
13 лет назад, # |
Rev. 2   Проголосовать: нравится +12 Проголосовать: не нравится
По своему опыту отмечу следующие моменты:

1. Надо не забывать писать в конце чекера (перед тем как уже готовы вернуть _ok) проверку на то, чтобы в output ничего небыло. Иначе выдавать PE с соответствющим комментарием.
Edit: testlib это делает сам

2. Я не знаю есть ли в testlib.h готовое решение для данного случая, в testlib.pas которым я пользовался небыло. Случай такой: мы хотим вывести комментарий типа "Expected %s, but found %s" со строками. Так вот надо быть аккуратным и обрезать строку, которую выдает участник, т.к. она может быть очень длинной.

3. Что будет если чекер упадет по run-time exception? Он как-то сам вернет 3 в качестве кода возврата? Или что угодно, но не ноль?
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Согласен. Дополню:
    1. Вообще, чекеры надо хорошенько тестить, почему-то многие пренебрегают;
    2. Используйте __testlib_part(const std::string& s);
    3. Маловероятно, что случиться run-time error и он вернет 1 или 2. Обычно, тестирующие системы рассматривают любой код кроме 0,1,2 так же как 3. Думаю, это хорошая практика.

    Спасибо, немного обновил статью.
  • 13 лет назад, # ^ |
      Проголосовать: нравится +13 Проголосовать: не нравится
    по 1. А разве тестлиб этого автоматически не проверяет, прежде чем вернуть ОК?
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Не дочитал замечание 1 до конца, подумал про другое (не забыть написать quitf). Отвечаю: да, тестлиб сам все проверит, output file должен быть вычитан до конца, иначе PE.
13 лет назад, # |
  Проголосовать: нравится +13 Проголосовать: не нравится
Спасибо, очень полезный текст, очень часто приходится всё это рассказывать, а теперь можно ссылочку давать!
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
1. А давайте сделаем функцию, которая будет писать комменты к вердиктам по шаблону. Например, что то типа f(x,y) возвращает строку "Expected x, found y". И таких самых разных. Тогда комментарий чекера будет стандартизован
2. Где можно почитать про описание формата токенов. Как его задавать, что можно использовать и т.д.
3. Может, автоматически обрезать комментарий до числа, указанного в testlib.h в какой-нибудь константе? Или только все аргументы.
4. inf.readInt(1, 100, "n"); - давно хотел узнать, зачем нужен "n"?
  • 13 лет назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится
    1. Ну кроме предложного таких generic вариантов я особо не вижу. Сделайте полное предложение, обсудим. Но не думаю, что будет очень удобно - дело в том, что если чекер нестандартный, то хочется комментария типа "Village #d contains #d houses, but %d expected", то есть комментарий должен отражать предметную область.

    2. Откройте testlib.h, все функции и классы, составляющие его API, имеют комментарии.

    3. Нет. Думаю, это дело тестирующий системы решать какой длины комментарий является адекватным.

    4. Чтобы в комментарий написать имя переменной. Удобно как в валидаторах, так и чекерах. Например, попросили в задаче вывести a, b и с, которые какие-то индексы от 1 до n. Вы и пишите readInt(1, n, "a"). Получится внятный комментарий.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      1. А можно тогда хотя бы парочку самых изощренных чекеров с codeforces. Просто если уж стандарт формировать, то ближе к проекту.
      2. Имелись в виду строки вида: [a-z]{1,100}.
      3. Константу можно и бесконечной по умолчанию сделать. Просто как возможность.
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        1. Особых правил каких-то нет. Из комментария должно быть понятно какая ошибка и желательно в чем.
        2. Да, я понял. У класса pattern есть описание.
        3. Не очень мне нравиться - неправильно в коде ограничивать так варварски длину. Все равно из префикса вывода будет мало что понятно.
        • 13 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          1. Хочется формализовать именно expected, found и т.п. Я же не знаю, как крутые люди пишут чекеры :)
          2. Да, действительно не заметил
          3. Разве? 
          "Expected: 'no solution', found '0 0 0 0 0 0 0 0 0 0 0 0...'". 
          "Expected: '0', found:'0 0 0 0 0 0 0 0...'". 
          "Expected 'a b c d e ...', found 'a,b,c,d,e,...'". 
          Еще нужны примеры?
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
    if (ja < pa)
        quitf
(_wa, "Jury has better answer: %d < %d", ja, pa);

   
if (ja > pa)
        quitf
(_wa, "Participant has better answer: %d < %d", pa, ja);

Второе _wa на самом деле _fail, в этом как раз основной пафос: если участник ВНЕЗАПНО нашёл ответ лучше, чем жюри, значит, где-то (в чекере, в решении, в генераторе?) у жюри точно есть баг. И жюри должно об этом как можно скорее узнать, а участник - получить не Wrong Answer, а Jury Error (хотя, например, testsys это сообщение участнику просто так не шлёт, зато начинает долбить жюри в консоль).
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
А есть ли способ заставить компилироваться чекеры на C++ быстрее, чем 10 секунд?
Что-нибудь вынести в отдельный файл и прекомпилировать его?
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Купите компьютер пошустрее. На моем (не самом современном) ноутбуке:
Running "g++ icmp.cpp", press ESC to terminate...
Program successfully terminated
  exit code:     0
  time consumed: 0.00 sec
  time passed:   2.05 sec
  peak memory:   1802240 bytes

Оверхед в две секунды думаю можно пережить. Меня он напрягает мало - не так часто я перекомпилирую генераторы, валидаторы и чекеры. Если есть желание, то попробуйте вынести некоторое содержимое testlib.h в cpp-файл. Попробуйте это проделать на последней версии 0.7.1 и ничего не меняйте - просто разнесите. Если получится хорошо, то можно добавить в транк и дистрибьютить и такой вариант.
13 лет назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится
Извините, что поднимаю эту тему, но вот интересно, где достать testlib на java, и как им пользоваться, компилировать и т.д.?
  • 13 лет назад, # ^ |
      Проголосовать: нравится -22 Проголосовать: не нравится
    testlib на java..... такого извращения еще не существует
    • 13 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

      Вроде как существует, и это проделки ИТМО

      (только вот зачем? polygon и testlib.h очень удобны, по-моему)

      • 13 лет назад, # ^ |
          Проголосовать: нравится +6 Проголосовать: не нравится
        Именно, можно порытся по архивам интернет-олимпиад на http://neerc.ifmo.ru/school
        Либо могу выложить, если надо.
        • 13 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Надо! В смысле было бы круто :-)
          • 13 лет назад, # ^ |
              Проголосовать: нравится +6 Проголосовать: не нравится
            Можно скачать архив последней ИО и там в папке с задачей jump лежит testlib4j.jar - тестлиб для Java, пример чекера Check.java и в файлах tests\doall.cmd и tests\onecheck.cmd можно посмотреть как они собираются (на самом деле можно чуть проще, чем там).
      • 13 лет назад, # ^ |
          Проголосовать: нравится +8 Проголосовать: не нравится
        Писать чекеры на Java как раз удобнее и безопаснее из-за ее более аккуратной работы с памятью.
        В чекерах важнее всего его надежность и защищенность.
  • 13 лет назад, # ^ |
      Проголосовать: нравится +6 Проголосовать: не нравится
    Выдумать! Хоть какое-то развлечение! ;-)

    public class TestLib {
    
    public static String ultraSneakyChecker(String pattern,
            ByteArrayOutputStream output)
    if (pattern.replace("\n", " ").trim().equals(
            output.toString().replaceAll("\\s+", " ").trim()) {
        return "AC";
    } // if
    return Math.random() < 0.37 ? "PE" : "WA";
    
    } // ultraSneakyChecker
    
    } // class TestLib
    
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    1) В папку вместе с чекером ложим testlib4j.jar
    2) Выполняем команды:
    javac -classpath testlib4j.jar Check.java -encoding utf8
    jar cf Check.jar *.class
    • 12 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

      Спасибо, собрал jar-файл по Вашему рецепту, но и как же его теперь запускать?
      Пытаюсь так:
      java -jar Check.jar <in> <out> <ans>
      Однако, ругается. Тогда гуглю ещё немного и пытаюсь так:
      java -classpath Check.jar Check <in> <out> <ans>
      Результат выглядит примерно так:
      <там много букв, посему он в правке>
      И теперь уже выгуглить ничего не удаётся. Так что же я делаю неправильно?

      • 12 лет назад, # ^ |
        Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

        Можно попробовать так - вроде следует из рецепта: 

        java -classpath "testlib4j.jar;Check.jar" Check <in> <out> <ans>
        
        • 12 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Нет, так тоже не работает. Собственно, я пытаюсь это сделать для чекеров из архива прошлогоднего NEERC. Закрадываются подозрения, что выложенный архив просто неполон, но я не вправе судить, потому что без помощи Google сам на Java даже "Hello, world" не напишу.
          Будет неплохо, если на этот архив посмотрит кто-нибудь из грамотных людей и вынесет вердикт.
          • 12 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится

            Прошу прощения, ответил по памяти :( Рекомендованный производителем способ все же такой:

            java -Xmx256M -Xss64M -cp testlib4j.jar;Check.jar ru.ifmo.testlib.CheckerFramework Check <in> <out> <ans>

            • 12 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится
              И этот способ точно так же не работает %)
              • 12 лет назад, # ^ |
                Rev. 2   Проголосовать: нравится +5 Проголосовать: не нравится

                На этот раз я его проверил, причем на предложенном архиве, честно-честно :) Похоже, за несколько лет борьбы с Java некоторые неочевидные вещи стали слишком привычными: подразумевал, что tetslib4j и check должны находиться в текущем каталоге, иначе надо прописывать точный путь к ним. Не могу придумать другой причины, по которой оно не работало бы.

                • 12 лет назад, # ^ |
                    Проголосовать: нравится 0 Проголосовать: не нравится
                  Они находились в текущем каталоге :)
                  Да ладно, я уже забил. Видимо, Java просто меня не любит.
            • 12 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится
              А вы не знаете как эти чекеры запуспить под ejudge? Они у меня запускаются, но при посылке в ejudge, получаю Check Failed и пишет что не может найти CheckerFramework...  
      • 12 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Я тоже собрал jar-ник, много раз пытался запустить, но все же не смог проверить :(
12 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Уважаемый Михаил Расихович!

Я очень высоко оцениваю и codeforces, и Polygon, и модификацию testlib, и благодарен за всю эту работу. И заранее прошу прощения, если мой вопрос окажется неприятным.

Тем не менее: почему на Полигоне нельзя прикручивать чекеры, написанные под checker.h, рекомендованный самим Черновым? Если у меня есть готовый и отлаженный чекер под checker.h, разве кому-то станет легче от того, что я буду вынужден переделывать, тратить время, и, возможно, допускать глупые технические ошибки?
  • 12 лет назад, # ^ |
      Проголосовать: нравится +12 Проголосовать: не нравится
    Есть несколько "но", почему бы я так делать не стал:
    1. чекеры на чистом C писать не очень удобно, STL очень помогает в написании простых, понятных и надежных чекеров, программы на C значительно менее безопасны, чем на С++;
    2. этот язык имеет слабое распространение в олимпиадной среде, их трудно будет поддерживать;
    3. не думаю, что такие чекеры компилируются и правильно работают под windows;
    4. ejudge использует нестандартные коды завершения процесса, они жестко захардкожены;
    5. не думаю, что такие чекеры компилируются широким кругом компиляторов C;
    6. высокий порог входа для использования чекера: например, быстренько скомпилировать чекер из командной строки неспециалисту С будет проблематично;
    7. неудачная модель дистрибуции зависимостей: вашему чекеру для компиляции нужен не только checker.h, то и огромное количество других файликов.
    Может я что-то не правильно понимаю, посмотрел в https://ejudge.ru/svn/ejudge/trunk/ejudge/checkers/
  • 12 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится -11 Проголосовать: не нравится

    Уважаемый Илья Николаевич!


    По большому счёту Михаил Расихович прав. 
    В дополнение и пользу его доводов приведу ещё два очень знакомых Вам примера:

    - тот же Юрий Яковлевич под свою систему просит писать чекеры на питоне.
    - да и в принципе любой администратор любой системы захочет видеть чекеры на том языке или в том формате, который удобно адаптируется именно под его систему.

    У нас, как Вы знаете, тоже свой подход и свои требования, именно поэтому Сергей Станиславович вынужден был полностью переписать паскалевские и сишные библиотеки чекеров "под систему". 

    Так что Чернов в принципе правильно рекомендовал, но его рекомендации касались другой системы проверки.

    P.S.: А в Питере вообще кажется сделали революционный прорыв - там, насколько я знаю (может и ошибаюсь), в последнее время чекеры пишут исключительно на Джаве.
    • 12 лет назад, # ^ |
        Проголосовать: нравится +11 Проголосовать: не нравится
      Вы немного не так поняли мою мысль. Все перечисленные пункты не имеют отношение к инфраструктуре Codeforces. На мой взгляд подход, придуманный довольно давно очень хорош и причин его менять мало: чекер это исполняемый файл (или близкий к этому), который использует параметры командной строки "input output [answer]", возвращает 0,1,2,3 и выводит в консоль комментарий. Переписывание чекеров - странное вложение сил.

      Чекеры на testlib4j мне не очень нравятся (несмотря на мою любовь к Java): они значительно медленнее запускаются (Quick Starter Service полностью не решает проблему долго старта JVM), они традиционно собираются в jar файл, которые не содержит зависимости и декорации main-class. Кажется, что удачнее было бы собирать их в Check.jar, который может быть запущен так: "java -jar Check.jar input output answer". В любом случае, сборка таких чекеров процесс довольно неприятный для тех, кто слабо знаком с Java - и это минус (скомпилировать cpp- или pas- чекер значительно проще).

      Я не спец по питону, но там тоже не все хорошо: его производительность в 5-50 раз меньше C++ или Pascal, а часто нетривиальные чекеры делают что-то умное. У него плохо с обратной совместимостью. Python 2 не совместим с Python 3. На каком питоне писать чекеры? Что делать с чекерами, написаными на Python 2 через пару лет? И, опять таки, питон не очень популярен в олимпиадной среде - ревьюить и поддерживать такие чекеры будет проблематично.
      • 12 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Может я не совсем точно выше высказался, но я именно это и имел ввиду.
        Плюс дополнительно высказал мысль о том, что тот, кто по разным причинам привязан к какой-то конкретной тестирующей системе, отдает предпочтение именно чекерам написанным под конкретную систему, и в случае с питоном также, опять же - в силу разных обстоятельств.

        Отсутствие стандартов - это с одной стороны плохо, но с другой стороны в этом есть и немало плюсов, в первую очередь связанных с тем, что подобные системы вынуждены постоянно развиваться, а не застыть. А от подобного развития выигрывают все.
        • 12 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Мне казалось, что и сам Polygon, и informatics.mccme.ru, добавлять задачи на который можно только через Polygon, используют черновский еджадж. Посему сравнение с НетОИшной  проверялкой (Кирилла Симонова) однозначно некорректно. А несовместимость с еджаджем казалась странной с учётом мнения, что системы используют еджадж.

          Я был не прав, считая, что и сам Polygon, и informatics.mccme.ru всё равно каким-то боком завязаны на еджадж?

          И ещё насчёт питона. АБСОЛЮТНО согласен, что НЕ СТ_О_ИТ связываться. На НетОИшном сервере от этого отсутствия обратной совместимости обычно прячутся, не обновляя старую версию. А где так сделать нельзя -- там начинается полный мрак...
          • 12 лет назад, # ^ |
              Проголосовать: нравится +3 Проголосовать: не нравится
            По ЛКШ-атскому опыту могу сказать, что ejudge спокойно работает с testkib.h. Ему вообще только exe от чекера нужен, а коды возврата там прописаны и включаются строкой #define EGUDGE  в начале чекера.
            • 12 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится
              testkib.h -- это testlib.h?
              exe -- это в смысле "исполняемый файл" без привязки именно к винде?

              Да верю я, что еджадж работает с тестлибом! Вопрос в том, что для заливания на informatics.mccme.ru задач, к которым есть готовые отлаженные чекеры под checker.h , приходится эти самые чекеры переписывать под testlib.h .

              Вышеприведённые аргументы более-менее убедили меня писать чекеры к новым задачам под testlib.h а не checker.h .  Но не убедили, что переписывание готовых (но написанных под checker.h) чекеров будет не просто неудобством, а полезным занятием.

              Хотя если на Полигоне действительно трудно разрешить checker.h -- что ж, будем подстраиваться под то, что есть...
            • 12 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится
              А вот это совсем не правильно! Для EJUDGE надо компилировать чекеры c -DEJUDGE, а за вставку #define на надо штрафовать!
              • 12 лет назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится
                Хм. Я не заливал задачки в еджадж руками, поэтому не уверен сам он компилирует чекер или его надо компилировать руками. Но я помню что скрипт для импорта из полигона писал что добавляет дефайн.
              • 12 лет назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится
                Большое спасибо за этот пост. Как раз искал, как избавиться от вердикта "Check failed".
12 лет назад, # |
  Проголосовать: нравится +16 Проголосовать: не нравится
Чтобы компилятор g++ выводил предупреждения при ошибках не соответствия строки форматирования передаваемым аргументам функции quitf, достаточно добавить в testlib.h три строки.

void quitf(TResult result, const char * format, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 2, 3)))
#endif

Хотелось бы, чтобы в свежую версию testlib включили эту фичу.
  • 12 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
    Ещё, если будет новая версия testlib, хотелось бы, чтобы был убран warning:

    In file included from check.cpp:1:0:
    testlib.h: In member function 'int random_t::next(long long unsigned int)':
    testlib.h:338:18: warning: comparison between signed and unsigned integer expressions

    (Upd: в testlib 0.7.2 строка 339, а не 338.)
    • 12 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Тогда уж тоже пожалуюсь, хотя мне опять скажут, что мне надо на исторический. g++ 3.4.5 выдает два экрана варнингов  если компилировать с -O2 -Wall. Без хотя бы одного из двух не выдает. testlib 0.6.4 похоже тоже старый, возможно проблема уже исправлена.
      • 12 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Если ворнинг "variable `cur' might have not been initialized", то это проблемы конкретно MinGW GCC 3.4.5, проявляющиеся не только с testlib. Они исправлены в более новых версиях MinGW.
»
11 лет назад, # |
  Проголосовать: нравится +5 Проголосовать: не нравится

У меня проблема следующего рода: разрабатывая задачи, я прекрасно понимаю, что их будут использовать школьные учителя в 90% знающие Pascal и не знающие C. Да и в рассылке от ЦПМК по информатике на региональный этап тоже приходят Pascal-чекеры. С другой стороны, я "пытаюсь" использовать ejudge, который живет под Linux и я хотел бы иметь возможность с легкостью перекомпилировать чекер под Linux, используя fpc. В тех версиях testlib.pas, которые я видел всегда есть "uses windows". Не подскажите где взять Linux-версию testlib.pas?

  • »
    »
    11 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Версия testlib-а на Паскале авторов из СПбГУ есть здесь: http://acm.math.spbu.ru/soft/testlib/ . Под linux чекеры должны компилироваться и работать. Есть пара несовместимостей с версией ИТМО (отсутствие NextLine?).