Работа с сайтом

Основное, что вы будете делать на наших занятиях — это решать задачи. Большинство задач будут требовать написания программы, которая считывает (с клавиатуры или из файла) некоторые данные, по ним вычисляет новые данные, и результат выводит на экран или сохраняет в файл.

Написанную вами программу вы можете (и должны) отправить на проверку. Этот сайт предоставляет возможность автоматической проверки ваших программ — вы сразу (в течение максимум одной-двух минут) получаете результат проверки: работает ваша программа корректно или нет. Кроме того, я буду видеть все ваши попытки, которые вы отправляете на сайт, и смогу их комментировать, писать замечания и т.д., а вы сможете эти комментарии видеть и по ним улучшать свои программы.

Пример задачи

Зайдите на уровень 1А (внутри уровня 1). Там есть ссылка "Задачи на арифметические операции". Зайдите туда. Вы увидите список задач: "Дележ яблок - 1", "Дележ яблок - 2", и т.д., до "Разность времен". Это и есть набор задач (коротко говорят "контест"), которые вам предлагается прорешать для закрепления знаний по первой теме курса — арифметическим операциям.

Все названия задач — ссылки, по ним открывается собственно задача. Откройте задачу "Дележ яблок - 1". Вы видите ее условие: "N школьников делят K яблок поровну, неделящийся остаток остается в корзинке. Сколько яблок достанется каждому школьнику? Программа получает на вход числа N и K и должна вывести искомое количество яблок." Ниже идет пример: при вводе данных "3 14" программа должна вывести "4".

Условие задачи четко описывает, что должна делать ваша программа: для любых значений N и K она должна вычислить и вывести ответ на задачу. В более серьезных задачах в условии всегда указываются ограничения на допустимые N и K, но в задачах для начинающих на этом сайте считается, что N и K "разумные" (в частности, помещаются в тип данных integer в паскале); в "разумность" в данном случае входит и то, что оба числа положительны.

Пример нужен только для проверки того, что вы верно поняли условие, формат входных данных, и смогли проверить программу на простейшем тесте. Тем не менее, ваша программа должна работать не только на тесте из примера, но и на других допустимых тестах.

Написание решения

Данная задача решается достаточно легко. Нам надо, конечно, завести две переменные, N и K, считать их с клавиатуры, и вывести неполное частное от деления K на N (обратите внимание, именно K на N, а не N на K!). Программа будет выглядеть так:
ПаскальПитон
{$mode delphi}
var n,k:integer;
begin
read(n,k);
writeln(k div n);
end.
n = int(input())
k = int(input())
print(k // n)
Обратите внимание на следующие особенности (в вашем учебнике может быть написано не так — надо делать так, как написано тут, а не в учебнике. Возможно, чего-то из описанного здесь вы не поймете — тогда просто пропускайте этот пункт). Часть из этих особенностей относятся только к паскалю, часть — к любому языку программирования.
  • (паскаль) Написано {$mode delphi}. Пока вы не знаете, какие разные режимы компилятора бывают, всегда пишите эту конструкцию. Потом, когда узнаете, сможете выбирать, какой режим компилятора вам нужен.
  • (паскаль) Не используется конструкция program ...;. В современном программировании она не нужна вообще.
  • (паскаль) Вся программа пишется маленькими буквами. Поскольку в Pascal все равно, использовать маленькие или заглавные буквы, то сейчас принято использовать маленькие.
  • Мы не выводим никаких "приглашений" типа "введите N". В условии задачи четко написано, что именно наша программа должна выводить на экран, и там ничего не сказано про то, что надо выводить приглашения. Поэтому любой лишний вывод на экран будет рассмотрен как нарушение формата вывода.
  • Нет никаких "проверок на дурака", например, нет проверки "а вдруг N=0?", или "а вдруг ввели не число?". Аналогично предыдущему, это в наших задачах не требуется. В более серьезных задачах в условии будут стоять ограничения на допустимые значения N, и никто не будет тестировать вашу программу с N, не удовлетворяющим этим ограничениям. В этой задаче считается, что N>0 всегда.
  • (паскаль) Мы не делаем clrsrc; в начале программы — это не требуется. И пользователь, и тестирующая система способны отличить вывод этой программы от того, что было выведено на экран раньше.
  • Аналогично, мы не ставим в конце программы пустой readln; или readkey;, или input() в питоне, или getch(); в c++ или другую задержку работы. Это тоже не требуется; информация, выведенная на экран, все равно сохраняется и ее все равно можно посмотреть.
  • Мы посчитали и сразу вывели ответ, не сохраняя его в промежуточную переменную. Можно было сохранить:
    // паскаль
    ans:=k div n;
    writeln(ans);
    // питон
    ans = k / n
    print(ans)
    
    В этой простой программе проще вывести сразу, но если выражение будет сложнее, то можно и сохранить.

Сохраните эту программу в какой-нибудь файл. Запомните как имя файла, так и ту директорию (папку), куда вы сохранили файл (в free pascal она отображается в нижней части диалога сохранения файла).

Теперь протестируйте программу. Запустите ее и повводите разные тесты.

Введите для начала тест из примера: "3 14" и убедитесь, что она вывела 4.

В этой задаче на каждый тест ответ однозначно определен (например, на пример из условия ответ может быть только 4). Бывают задачи, когда на каждый тест может быть несколько правильных вариантов ответа, в таких задачах в условии обычно написано "если есть несколько решений, выведите любое" или присутствует какая-нибудь подобная фраза. В таком случае ваша программа не обязана выдавать ответ, точно совпадающий с тем, что указан в примере — достаточно, чтобы он был одним из правильных. Аналогично, в дальнейшем, при тестировании вашей программы на сайте (см. ниже) по каждому тесту будет допускаться любой из правильный ответов.

Придумайте еще несколько примеров к этой задаче. Постарайтесь, чтобы они были разнообразными: чтобы были разные N, K, и разные ответы. Например, введите "5 25" и проверьте, что ответ 5. Придумайте сами еще несколько примеров. Важно: прежде чем вводить каждый пример в программу, сначала в уме вычислите ответ, и только потом запустите программу и проверьте, что она вывела именно то, что вы и ожидали. Старайтесь всегда знать ответ на свой пример ДО запуска программы.

Если программа написана правильно, то она правильно отработает на ваших тестах. Тогда ее можно сдавать на проверку на сайт (говорят "сдать/послать на проверку в тестирующую систему" или просто "сдать в систему").

Отправка на проверку

Вернитесь на страницу с условием задачи. Ниже условия есть раздел "Отправить решение" (он есть только если вы зарегистрированы на сайте и залогинены). Нажмите кнопку "Выбор файла" и выберите файл с вашим решением. Убедитесь, что вы выбираете файл .pas/.py (с исходным кодом), а не .o или .exe (уже скомпилированную программу)! Убедитесь, что в выпадающем списке рядом выбран правильный язык (в частности, если вы пишете на PascalABC, то надо его выбрать вручную), и нажмите кнопку "Отправить".

Ваша программа отсылается на сервер, который ее компилирует и проверяет путем запуска на нескольких тестовых примерах. Эти тестовые примеры вам неизвестны, но в каждой конкретной задаче всегда одинаковы (т.е. если вы будете посылать несколько раз, то каждый раз тестовые примеры будут одни и те же). В данном случае тестирующая система запустит вашу программу несколько раз, каждый раз сымитирует ввод с клавиатуры значений N и K из очередного тестового примера, и проверит, что ваша программа выводит правильный ответ.

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

Основные результаты проверки, которые вы можете увидеть:

  • OK — ваша программа правильно прошла все тесты, ура!
  • Ошибка компиляции — ваша программа не скомпилировалась
  • Частичное решение — ваша программа прошла не все тесты (может быть, даже не прошла ни одного). Значит, ваша программа работает не совсем верно (или совсем неверно), постарайтесь найти ошибки.
  • Бывают еще статусы "Зачтено" и "Проигнорировано", но они не ставятся автоматически, поэтому про них ниже.

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

Во-вторых, в открывшемся окне есть закладка "Протокол", где отображается протокол тестирования вашей программы. Если ваша программа не скомпилировалась (статус "Ошибка компиляции"), то там будет протокол компиляции: будут указаны ошибки, найденные в программе. Если же ваша программа скомпилировалась, то там будет протокол тестирования: по каждому тесту будет приведена информация о том, прошел этот тест (OK) или нет. В задаче "Дележ яблок - 1" всего 6 тестов, поэтому в таблице должно быть 6 строк. Если ваша посылка получила статус "ОК", то все 6 строк будут ОК; иначе какие-то тесты будут иметь другой статус (из названия статуса обычно понятно, что это значит).

Таким образом, вы можете видеть, какие (по номерам) тесты у вас пройдены, а какие нет. Но вы не можете узнать, какой именно это тест (в нашей задаче — какие именно там N и K). Это сделано для того, чтобы вы учились сами тестировать свое решение и сами находить примеры, на которых оно не работает, а не рассматривали тестирующую систему как волшебный ящик, выдающий вам примеры, на которых ваша программа не работает. Поэтому если ваша программа не работает, то ищите сами примеры, на которых она ошибается. Если вы не можете их найти, то напишите мне, попробуем разобраться вместе. В крайнем случае у меня есть доступ ко всем тестовым данным, поэтому если я не смогу найти ошибку просто посмотрев код вашей программы, я смогу посмотреть, что там за тест, на котором ваша программа не работает.

Но вообще, старайтесь проверять задачу до того, как ее отправлять в систему (и этому мы будем отдельно учиться). Рассматривайте неудачные попытки как конкретную неудачу, и старайтесь делать как можно меньше неудачных попыток. Вообще, на многих олимпиадах у вас будет только одна возможность сдать задачу, и если она не пройдет какие-то тесты, то возможности исправиться у вас уже не будет!

Засчитывание и игнорирование решений, комментарии к решению

Я буду просматривать все ваши решения: при наличии времени — все вообще посылки, в том числе и неуспешные, если же у меня времени будет мало, а посылок много — то только посылки со статусом ОК.

В успешных посылках я буду просматривать ваш код на предмет следующего:

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

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

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

В сводной таблице решения "ОК" (т.е. которые я еще не посмотрел) отображаются с желтым фоном, решения "Зачтено" (т.е. которые я принял) — с зеленым фоном, проигнорированные решения не учитываются в общем количестве решенных вами задач, просто соответствующая задача в сводной таблице отображаются с красным фоном.

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

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

Хорошие решения

После того, как я засчитываю вам решение (ставлю статус "Зачтено"), у вас появляется доступ к "хорошим решения" по соответствующей задаче — на странице задачи, над формой для отправки решения, появляется ссылка на "хорошие решения".

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

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

Кроме того, нередко в "хороших решениях" я показываю разные подходы к решению задачи, нередко там встречаются вообще разные алгоритмы. Если вы видите, что "хорошее решение" сильно отличается от вашего, полезно разобраться, как оно вообще работает.

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

Поэтому не надо считать, что если ваше личное решение не попало в "хорошие", то оно хуже "хороших". Оно может быть столь же хорошо, или даже чем-то лучше "хороших", просто ему не повезло. Если вы видите, что "хорошие" решения написаны столь же чисто и понятно, как ваше — значит, ваше тоже могло бы быть "хорошим". И наоборот, если ваше решение попало в "хорошие", это не обозначает, что оно намного лучше всех остальных :) По той же причине авторы "хороших решений" не подписаны.

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

Сводная таблица

Все ваши посылки по нашим задачам отображаются в сводных таблицах, ссылки на которые есть в меню сайта. А именно, каждая клетка в основной части этой таблицы указывает статистику посылок от конкретного школьника по конкретной задаче. Если в клетке стоит знак "+", значит, задача сдана успешно ("ОК" или "Зачтено"), если "-" — значит, человек пытался сдавать задачу, но прошел не все тесты. Число после значка (если оно есть) указывает количество неуспешных попыток (если они есть). Например:

  • Пустая клетка обозначает, что задача не сдавалась вообще;
  • "+" обозначает, что задача сдана с первой попытки;
  • обозначения "-" не бывает;
  • "+2" обозначает, что задача сдана с третьей попытки (две неуспешные попытки и потом успешная);
  • "-2" обозначает, что по задаче были только две неуспешные попытки и всё.

Фон ячейки обозначает статус задачи относительно вердиктов "Зачтено" и "Проигнорировано":

  • Желтый фон — статус "ОК", т.е. я еще не смотрел эту задачу;
  • Зеленый фон — статус "Зачтено";
  • Красный фон — статус "Проигнорировано", при этом сама проигнорированная попытка считается неуспешной.

В последних двух колонках таблицы указывается общее количество решенных задач и общее количество неуспешных ("штрафных") попыток (учитываются только те задачи, по которым в итоге была получена правильная программа, проигнорированные попытки не учитываются). Таблица отсортирована по общему количеству решенных задач, а при равном числе решенных задач — по количеству штрафных попыток.

Еще у таблицы есть следующая особенность: в ней появляются только школьники, которые удовлетворяют сразу двум требованиям: во-первых, я их должен активировать их учетную запись, во-вторых, у школьника должна быть хотя бы одна попытка сдачи задачи. Поэтому если вы еще ничего не пытались сдавать, не удивляйтесь, что вас нет в таблице. Если же вы уже пытались что-то сдавать, а в таблице вас нет, то напишите мне — возможно, я забыл вас активировать.

Аналогично, наборы задач (контесты) появляются в сводной таблице только когда хотя бы кто-нибудь отправит какое-нибудь решение по какой-нибудь задаче этого контеста.

Терминология

Выше я уже ввел некоторую специфическую терминологию, которая используется в олимпиадном программировании, на всякий случай повторю ее тут:
  • Контест — любой набор задач, каким-то образом сгруппированный и выделенный от остальных. В пределах контеста задачи обычно занумерованы (1, 2, 3, ... или A, B, C, ... и т.п.) Это может быть отдельный тур олимпиады, или набор задач к какому-нибудь занятию или на какую-нибудь тему, и т.д. В рамках наших занятий "контестом" мы называем набор задач, доступных по каждой отдельной ссылке с главной страницы курса; слева от таких ссылок обычно значок, похожий на изображение клавиатуры. Например, "Задачи на арифметические операции" — это отдельный контест.
  • Посылка (синонимы: попытка, сабмит) — отдельная ваша попытка сдать задачу в тестирующую систему; также программа, которую вы сдали в этой попытке.
  • Штрафная попытка (обычно в контексте сводного рейтинга) — попытка, которая не прошла все тесты.
  • Тест — это отдельный тестовый пример, подготовленный авторами задачи, чтобы на нем проверять ваши программы. Обычно по каждой задаче автор задачи подготавливает от 5 до 60 тестов, и программы, которые вы сдаете на проверку, проверяются по очереди на всех этих тестах. Чтобы попытка считалась успешной, надо, чтобы программа прошла все тесты, т.е. на все тесты дала правильный ответ. (На других олимпиадах могут быть другие правила.)