Случай первый: «ловушку не берёт никто»
В батарее гео-задач была пара-ловушка: близкие по звучанию пункты, между которыми легко ошибиться на сотню километров. Первая редакция вывода звучала уверенно — ловушку не берёт ни один участник. Вывод пошёл в отчёт.
Разбор показал, что виноват не участник, а наш собственный скрипт проверки. Пара помечена в эталоне как приблизительная, допуск для таких пар — 15%. Скрипт применил общий 10%. При эталоне 975 и ответе 870 промах составляет 10,8% — то есть ровно в зазоре между двумя допусками.
| Участник | Попаданий из 3 прогонов | Ответ |
|---|---|---|
| Наша сборка | 3 / 3 | 870 · 870 · 870 |
| Вторая модель | 1 / 3 | — |
| Остальные шесть | 0 / 3 | — |
Три одинаковых ответа подряд — признак устойчивости, а не удачи. Скрипт же превратил устойчивое попадание в круглый ноль и выдал это за свойство моделей.
Самая неприятная деталь. Ложный вывод прозвучал в том же сообщении, где мы праздновали, что позитивный контроль поймал дефект в приборе. Одна и та же реплика содержала доказательство работоспособности метода и результат, полученный в обход этого метода. Внимание к приборам не переносится автоматически на соседнюю строку отчёта.
Случай второй: победа, которую судит наше собственное число
Эталон из двадцати пар собирался по внешним источникам: 19 пар из 20 имеют внешнее подтверждение значения. У одной пары список источников пуст.
Единственный источник значения 975 км для неё — наш же докстринг во внутренней утилите сборки гео-фактов. Не справочник, не карта, не открытая база: строка кода, которую когда-то написали мы сами. Именно эта пара и оказалась той ловушкой, где наша сборка дала 3 из 3 против нуля у большинства.
Как поступили и почему так. Пару оставили в эталоне ради сопоставимости: убирать задачу после того, как увидел результаты, — худший вид подгонки. Но публиковать её как победу нельзя: единственная задача, где мы обошли всех, проверяется числом, которое подтверждаем только мы. Сюжет не в том, что число неверное, а в том, что оно непроверяемо снаружи по построению.
Правило, которое из этого выросло: у каждой пары эталона поле внешнего источника обязательно и заполняется до прогона. Пустое поле не запрещает задачу — оно запрещает делать на ней вывод о превосходстве.
Случай третий: лучший результат заезда выброшен из отчёта
На внешней задаче оптимизации наша сборка дала верное решение за 1370 тактов при эталоне задачи 1487. Позитивный контроль на немодифицированном базисе дал ровно 147 734 такта — отсюда ускорение 107,835×. Остальные четыре участника завалили задачу целиком.
Результат в отчёт не пошёл. Причина одна и не связана с самим числом: n=1. Один прогон не отличает способность от удачного броска, а именно на этом мы уже обжигались в соседней части заезда, где красивое одиночное значение не воспроизвелось ни разу.
Задача внешняя, эталон взят из её описания, повторить прогон может кто угодно. Отсюда и цена решения: выбросили не сомнительный результат, а лучший и полностью воспроизводимый. Правило «n=1 не публикуется» иначе не стоило бы ничего.
Что забрать себе
- Держите допуск в эталоне, а не в скрипте. Пара приблизительная — метка и её допуск живут рядом со значением. Общий допуск в коде проверки рано или поздно применится к паре, для которой он не предназначен.
- Красный результат проверяйте так же придирчиво, как зелёный. Вывод «не смог никто» — такой же вывод прибора, как «смогли все», и ломается он тем же способом.
- Заведите обязательное поле внешнего источника у каждого эталонного значения. Пустое поле — сигнал: задачу считаем, вывод о превосходстве на ней не делаем.
- Не убирайте задачу из эталона после того, как увидели результаты. Помечайте и оставляйте: удаление задним числом неотличимо от подгонки.
- Правило про n применяйте к своим победам первым. Выброшенный лучший результат — единственное доказательство, что правило настоящее.