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

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

Я очень люблю формат соревнований Surprise/Unknown Language Round. Теоретически я люблю в них участвовать, но на практике чаще получается, что я их провожу. Что же в них мне так дорого?

  1. Необычность. В определенный момент (который у меня настал достаточно быстро) традиционные соревнования приедаются и сливаются в одно размытое пятно. Если задуматься, из 70 СРМов и десятка CF-раундов, в которых я участвовала, я отчетливо помню от силы пару штук — SRM с задачей MooresLaw (ах, какие челленджи там были! И это, кажется, мое единственное первое место в комнате), отборочный раунд TCO, в котором я прошла за счет сданного в последний момент 500pt, GCJ-раунд из тех времен, когда он проводился еще на базе TopCoder, в котором я безнадежно застряла в парсинге условия и так и не добралась до собственно решения... и, пожалуй, все. С марафонами дело обстоит получше, не в последнюю очередь из-за того, что их было меньше, и каждому отдельно взятому раунду уделялось больше времени и внимания. Но все-таки необычные соревнования оставляют самые яркие и долгоживущие впечатления.

  2. Соответствие моим навыкам и умениям :-) Языки, в которых нет циклов, строк или еще чего-то такого же привычного, не шокируют меня и не угрожают моему психическому здоровью. Нет, конечно, существуют языки, которых я опасаюсь, но их на ULR пока не попадалось и вряд ли попадутся. А в остальном я получаю массу удовольствия от раскопок документации чего-нибудь ненормального (особенно если эта документация есть), от внезапных озарений "так вот как ты думаешь!" и от того, как что-то жутковатое, наспех скомпонованное из фрагментов примеров кода, вдруг собирается воедино и начинает работать.

  3. Практическая ценность — после раунда (а если я автор, то и до) свежеизученный язык пополняет собой ряды экспонатов Прогопедии и RosettaCode.

  4. Послераундовые комментарии. Удивительно, насколько не все люди одинаково хорошо адаптированы к языкам, отличным от C++, и насколько бурно они на это реагируют :-)

С авторской точки зрения, есть еще ряд преимуществ по сравнению с Див2-раундом. Они сводятся к тому, что готовить ULR проще: более простые задачи приводят к более лаконичным условиям, более простым авторским решениям, валидаторам и генераторам тестов (а некоторые из них можно нахально позаимствовать из прошлых раундов), меньшим объемам тестерской критики и соответственно правок в последнюю минуту, наконец, к меньшему количеству вопросов во время раунда (хотя обязательно кто-нибудь спрашивает "А что, на C++ точно нельзя?" — это до сих пор остается для меня загадкой). Из недостатков — большее количество задач (что тяжело само по себе) и меньшая аудитория (в самом удачном Befunge-раунде было 340 участников, с Див2-раундом, даже самым неудачным, не сравнить). Впрочем, я надеюсь, что со временем (языков-то еще лет на 50 хватит) публика проникнется концепцией, и раунды станут более людными.

К чему это я? К тому, что лично мне (хотя, думаю, MikeMirzayanov тоже) хотелось бы видеть больше ULR, хороших и разных. А для этого недостаточно подобрать удачный язык, нужен еще и автор, который этот язык вдумчиво выберет, изучит (или освежит в памяти) и конвертирует в подходящий набор задач. Одной меня в этой роли явно недостаточно (да и поучаствовать иногда хочется). Поэтому позволю себе дать несколько советов начинающему автору ULR — вдруг кто да вдохновится?

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

  • Сразу вычеркиваем языки, на которых просто невозможно написать 10 существенно разных задач (HQ9+, кхе-кхе).
  • Нет повести печальнее на свете, чем "неизвестный и удивительный" процедурный язык с си- или паскалеподобным синтаксисом! Пусть он отличается от общеизвестных какими-то нюансами реализации объектно-ориентированной парадигмы или сборки мусора, веб-ориентированностью или удобством командной разработки — вы все равно не сможете подобрать задачи, демонстрирующие это за отведенные на контест 2-3 часа. Раз так, фокус раунда придется сдвинуть с освоения новой парадигмы на решение старых добрых алго-задач с небольшими отличиями в синтаксисе и библиотечных функциях — а это уже совсем не то.
  • Язык должен позволять легкий старт. Насколько сложно установить интерпретатор и запустить программу-пример? Сколько документации есть у языка — целый сайт или одна страница? Сколько примеров программ есть на этом языке — две, входящие в описание языка на авторском сайте, или сотня в разных блогах и хрестоматиях программирования? Например, Agda требует сверхчеловеческих усилий по ее установке — лично я так и не осилила, пришлось звать на помощь мужа :-) Многие очаровательные эзотерические языки отпадают, потому что на них написано в общей сложности две программы, из них одна Hello, World. (Отмечу, что наличие или отсутствие русскоязычной документации лично для меня не является критически важным — толковые русскоязычные описания/сообщества есть только для достаточно мейнстримных языков, которые в силу этого не подходят для ULR).
  • Кроме того, язык должен быть доступен для основных платформ. Нет, интерпретатор под Андроид не обязателен, но Windows (для тестирующей системы) и Linux (во избежание ущемления прав линуксоидов, меня в том числе) — must have. Удобны также онлайн-интерпретаторы. Насчет доступности языка на ideone — даже не знаю; я этим сайтом пользуюсь регулярно, но большинство людей то ли не осознает, что о настройках приватности кода нужно позаботиться (а ведь я пишу об этом в каждом анонсе!), то ли не сильно беспокоятся об этом, а зря.
  • Язык не должен раздражать. Нет, конечно, для любого языка найдутся люди, которых он будет раздражать (или лучше сказать, найдутся люди, которых будет раздражать любой язык?), но если язык нервирует даже вас, автора раунда, то что-то тут не так. Собственно, из примерно таких соображений в COBOL-раунде было всего пять задач: на решении к пятой из них я поймала себя на кровожадном щелкании зубами. Раунд по Brainfuck я не буду давать не только потому, что он достаточно хорошо изучен, а и потому, что написание на нем программ требует не столько изобретательности, сколько нечеловеческого терпения и внимательности.
  • Выбор языка для конкретного раунда зависит не только от харизмы самого языка, но и от того, какие языки фигурировали в прошлых раундах. Не стоит давать два похожих языка подряд — ведь вся прелесть ULR состоит в том, чтобы узнать что-то новое. Здесь схожесть оценивается не столько по синтаксису и общему виду программ, сколько по основным парадигмам языка. Befunge — стековый эзотерический язык, значит, остальную эзотерику (90% которой основано на стеках в той или иной форме) придерживаем на пару раундов (хмм, кстати, эти пара раундов уже прошли...). COBOL — ретро-язык? Значит, Ada и Algol откладываются на потом.

Допустим, вы последовали этим советам и определились с языком. Теперь пора выбирать задачи.

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

Раунд Участников 1 2 3 4 5 6+
Factor официальный ~340 299 166 107 69 32 16
Factor общий ~500 409 221 147 99 56 29
COBOL ~270 141 72 23 10 8
Befunge ~340 278 197 161 119 81 67
Pike ~270 213 176 140 111 91 65
Io ~220 187 167 138 100 67 48
Tcl ~290 234 188 147 111 90 53

Как подбирать содержание задач? Лично я считаю, что задачи должны задавать не вопрос "Как решить?", а вопрос "Как реализовать?", то есть давать несложные задания с очевидными алгоритмами, чтобы основной загвоздкой было их кодирование средствами языка. Разные задачи одной сложности должны освещать разные аспекты языка (например, математику и работу со строками), с возрастанием сложности нужно раскрывать новые, более затейливые концепции (например, циклы, условные переходы и работа с "памятью" в Befunge или циклы и структуры данных в COBOL).

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

Может быть сложно изобрести так много простых (по сравнению с типичным Див2) задач, еще и на разные темы. Моим бесперебойным источником вдохновения вот уже третий раунд служит RosettaCode — сборник заданий разной сложности на разных языках. (Хм, где можно получить гонорар за ненавязчивую тематическую рекламу?) Разумеется, нужно выбирать только из заданий, которые на языке раунда еще не решены, иначе теряется весь смысл. Некоторые задачи я заимствую из прошлых раундов — бывает любопытно показать, насколько по-разному одно и то же задание решается на языках с разной парадигмой, да и инфраструктура задачи уже готова. Над задачами посложнее, конечно, приходится подумать, но будь это тривиально, профессии райтера не существовало бы :-)

Пожалуй, это все, что можно посоветовать начинающему автору ULR без того, чтобы скатиться до "так, вот прикольный язык, вот список задач, действуй" :-)

Напоследок предложу пару идей для популяризации формата ULR — я буду считать свою миссию евангелиста выполненной, когда на каждый раунд будет приходить не меньше 500 человек, решающих хотя бы одну задачу.

  1. Рейтинг. Самое очевидное решение для любых достаточно регулярных соревнований с устоявшимся форматом — ввести рейтинг по их результатам. Невероятно, но факт — многим людям нравится наблюдать за изменением циферок в их профиле и даже что-то делать для того, чтобы эти изменения имели нужный знак. Броское название, отражающее суть происходящего на раундах, — скажем, что-то однокоренное с "фанатом", "маньяком" или хотя бы "полиглотом" — и дело в шляпе.

  2. Призы. Это ужасно меркантильно, но даже больше, чем рейтинг, люди любят призы — материальные свидетельства славных побед. А ULR — отличная возможность раздобыть футболку не только тем знатным алгоритмистам, которые футболками только что пол не моют, а и простым смертным, для которых она ценнее горностаевой мантии. Не знаю, сколько это стоит в России, но мне кажется, одну футболку с ехидной надписью (скажем, "Я выучил (language name) за три часа, и все, что я получил, — эта дурацкая футболка!") для победителя раунда выделить можно, а?

  3. Достижения. Лично я к бэджикам в профиле отношусь достаточно спокойно (если, конечно, профиль не на Хабре), но мне кажется, если не рейтинг, то хотя бы звездочки с надписью "(language name)" и цветом, зависящим от количества решенных на раунде задач (или от занятого места), ввести можно. К другим достижениям тоже относится — та же медаль Кормана или победа в каком-нибудь чемпионате на основании Codeforces :-)

Вот теперь точно все. Увидимся на следующем ULR — кто, кстати, его пишет? :-)

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

»
12 лет назад, # |
  Проголосовать: нравится +18 Проголосовать: не нравится

поскольку я испытал на своей шкуре, что такое участвовать в SLR, то хотел бы высказать своё мнение касательно задач

я считаю, что давать первые 4-5 задач на тему "найдите такую-то возможность в языке и получите за это плюс" — это неправильно

всё-таки раунд должен вынуждать не только читать инструкции, но и заставлять что-то делать своими руками даже на ранних стадиях; пусть это будут 2-3 строчки кода, но своего кода, а не копипасты из Прогопедии с изменением пары символов

»
12 лет назад, # |
Rev. 3   Проголосовать: нравится +9 Проголосовать: не нравится

Я участвовал не на многих таких раундах, но Befunge мне правда понравился, я этот контест надолго запомню :) Первый взгляд на код этой программы вызывает мысли в голове "неужели эта фигняи правда ещё и работает".. :)

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

    А мне вот больше понравились Tcl и Io, чем Befunge. Они больше похожи на нормальные языки, но при этом все так же надо рыться в документации, так что смысл раунда вроде бы не пропадает.

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

      Ну в том то и прикол, в непохожести их на нормальные языки. Точнее он очень не похож на нормальный язык, но в месте с этим на нём можно писать нормальные программы, ну и плюс его стэковость тоже прикольно. И ещё я потом показывал людям код своих программ на Befunge и с гордостью говорил, что это рабочий код одной из программ и я лично его писал :) У людей глаза на лоб лезут... ну и просто прикольные картинки можно порисовать этим языком :) Мне кажется более удачного языка нельзя придумать...

»
12 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
существуют языки, которых я опасаюсь, но их на ULR пока не попадалось и вряд ли попадутся

А вы не опасаетесь языка КОБОЛ? Вот я теперь опасаюсь.

UPD. Извиняюсь, сейчас нашёл строки про него. Не специалист, но разве в Ada такой же странный синтаксис? Тут ведь не в ретровости дело, наверное.

Кстати, Factor вот очень порадовал :)

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

    А что его опасаться, нормальный язык. Опасаюсь я скорее Malbolge и иже с ним.

    Edit. А что, кто-то пробовал кодить на Malbolge и получилось проще и приятнее, чем на COBOL?

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

      Там какие-то ужасные бюрократические конструкции, и отступы ещё надо делать, насколько помню (после 0 задач постарался его забыть). Это же неприятно.

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

        Можешь рассказать это авторам python :)

»
12 лет назад, # |
  Проголосовать: нравится +37 Проголосовать: не нравится

Я хочу внести предложение — делать SLR подлиннее, хотя бы 4 часа вместо 2-х. Не у всех конечно, но лично у меня а wildcard'е очень остро ощущалась нехватка времени. Потому что за 2 часа нужно успеть вникнуть в непривычную парадигму языка, в его синтаксис, возможно, поизучать стандартные библиотеки, а еще решить несколько задач, помучившись с ошибками компиляции. Для тех, кто по природе тугодум — очень серьезное испытание. Как только начинаешь понимать что-то в языке — контест заканчивается.

Тем более, я полностью согласна с Alex_KPR, отписавшимся выше. Посмотрите для примера на решения неофициального победителя последнего SLR nab. У него самое длинное решение — 4 (!) строчки кода. Безусловно, он молодец, но разве можно называть это программированием?! Если бы времени было побольше — можно было бы добавить в проблемсет задач, в которых можно чего-то посерьезнее написать, строчек на 20-30 хотя бы. Мне кажется, сильным участникам было бы интересно побороться с такими задачами, а у более слабых будет шанс за это время сдать хоть что-нибудь)

Разумеется, вижу основной недостаток своего предложения — не у всех найдется 4-5 часов времени на участие в SLR. С другой стороны, автор при тех же затратах сил на изучение языка и приспособление его к проведению раунда доставит в 2 раза больше удовольствия тем, кто примет участие.

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

    Восприятие времени на раунде зависит от того, в чем человек привык участвовать. Я начинала с ТопКодера; для меня двухчасовой раунд — уже тяжело, а 4-5 часов подряд я готова посвятить только очень особенным соревнованиям (типа Challenge24) и не чаще пары раз в год. Для ACMщиков это, видимо, иначе.

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

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

      Тут смотря какую цель ставить перед SLR. Если это просто рассматривать как развлечение в выходные — тогда все ОК, кто не хочет — развлекайтесь по-своему. А вот если он проводится как этап отбора в официальном турнире с призами и онсайтом — это совсем другое дело. Красть у людей время становится не так стыдно (вспомним VK Cup 2012 Уайлд-кард раунд 2) и при этом возникает дополнительная ответственность за качество раунда.

      Два или четыре часа — непринципиально, когда есть одна задача на поиск в ширину. Кто знает поиск в ширину и умеет применять — напишет за 2, кто не знает — не напишет за 4. В SLR человек может протупить первые 2 часа, но потом немного освоиться с языком и все быстро порешать. Это мое субъективное мнение, хотя не исключено его совпадение с чьим-нибудь еще.

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

        По-моему, в при увеличении длительности до 4 часов SLR потеряет большую часть своей привлекательности. В текущем формате побеждает тот, кто успеет быстрее всего освоить незнакомый язык, найти нужные функции в библиотеке, настроить транслятор у себя на машине и т.п. Иначе раунд будет сводиться к построению отображения из родного С++ в этот необычный язык.

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

        Каждый раунд при этом получается индивидуальным — если последний SLR сводился к поиску возможностей в языке, то, например, раунд с Befunge — полная противоположность.

        Также немаловажный фактор — дать шанс на победу более слабым в обычном формате участникам. Меня, например, мотивировало 5-е место на одном из SLR.

»
12 лет назад, # |
  Проголосовать: нравится +36 Проголосовать: не нравится

This is a great post, and your Factor contest in particular was really awesome. I'd definitely like to run one of these, and I have a few languages in mind that I think would work well. How should one go about getting a round set up?

»
12 лет назад, # |
  Проголосовать: нравится +5 Проголосовать: не нравится

I think SLRs add a lot of value to this platform! In the past I only had time to do the COBOL and Befunge rounds, and especially the latter one I enjoyed a lot. And I share your experience regarding regular competitions to some extent. I suppose it's because I always end up with similar approaches. Check if greedy algorithm works? No? DP, maybe? ... and once you found an approach the solutions don't look that different from one another. With a surprise language the focus shifts to figuring out how to actually implement the approach you have sketched in your head and I feel a bit like MacGyver when I succeed :)

One question: How much time do you spend on preparing a round?

Btw, the April's Fools Contest was great too!

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

    Over a week, I think:

    • a day or two on selecting the language (checking the interpreters, manuals etc. — sometimes I pick a language but drop it because I don't like the manual or decide that it will be too irritating/hard to learn),
    • a couple of days selecting and coding the problems. Here goes updating Progopedia article, if needed (for Factor, for example, I had it ready beforehand but as I started to code the solutions I realized that the examples in the article can be made shorter and more neat, so I had to update them),
    • three days or so putting the problems into Polygon (that's Codeforces' system for setting rounds) with reference solutions, validators and tests. It's amazing how long it takes even for simple problems — I can do over three problems per day only if I copy them from my previous rounds. Here goes resolving any problems we might encounter while setting up the testing system for the new language,
    • and finally around half a day writing the editorial. I try to do this during the round itself, while I have to follow it anyways, but it usually takes longer than that.
»
12 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

По-моему, Surprise/Unknown Language Rounds заслуживают быть аргументом в споре "спортивное программирование != промышленное программирование". Если в обычном формате олимпиад (особенно с пост-проверкой) спортивное программирование еще хоть как-то похоже на подготовку к промышленному, то в случае ULR это сходство примерно как у дорог в Самаре и в Берлине. Т.е. общее только непонятно откуда взявшееся слово в одном из названий.