Вдохновившись этой статьей от СКБ Контур, решили провести Code Retreat у себя на факультете (Томский государственный университет, факультет информатики). Правда у нас целью было не обучение каким-то конкретным технологиям, а скорее просто знакомство (половина участников с 1-2 курсов), фан и немного ненормального программирования.
Кратко о формате мероприятия
- Сессии по 45 минут (всего было 4 сессии + вводный квест).
- Между сессиями перерыв 15 минут с кофе и плюшками.
- Одна задача на все сессии, но каждую сессию объявляется ограничение на этот раунд.
- Программирование идет в парах (Кодер и Навигатор), у пары один компьютер, одновременно код пишет только один человек (Кодер).
- Каждую сессию пары меняются.
- Каждые 11 минут пара меняется ролями.
Стандартное для формата ограничение «после каждой сессии код удаляется» было принято не вводить на нашем мероприятии, т.к. не было большой уверенности, что все справятся с заданием в установленный срок (все-таки участники – не профессиональные программисты, а по большей части студенты младших курсов).
Кроме того, для увеличения показателя FpM (fun per minute) были введены дополнительные ограничения, не относящиеся к формату Code Retreat:
- Каждый раунд объявляется еще одно общее ограничение увеселительного характера.
- Каждая команда получает персональное ограничение увеселительного характера.
Задание
Теперь перейдем к конкретике. Задача – написать интерпретатор эзотерического языка программирования HQ9+. Заданием на 0-й раунда было определить задание. Для этого в социальных сетях (Twitter, Google+, Vkontakte) под тегом #coderetreat4csd публиковались подсказки (текстовые и картинки). Всего было 3 ветки подсказок, которые заканчивались ответами «Hello, world!», «Quine», «99 bottles of beer» (3 основные составляющие языка HQ9+), которые должны были навести на правильный ответ. Не буду перечислять сами задания квеста, скажу лишь, что она были направлены на изучение особенностей различных технологий: rarjpg, base64, обфускация кода (на примере js), куэр коды с картинками (серьезные ребята, не надо скептически морщить лоб – для первого-второго курса это довольно неочевидные вещи, особенно когда ты еще ни разу в жизни с ними не встречался, да и время на 0-й раунд было ограничено 30-ю минутами).
В итоге, квест за отведенное время никто так и не решил, хотя по отдельности каждую ветку квеста прошла хотя бы одна команда. С помощью наводящих вопросов задание было донесено до участников, после чего все пошли кушать и рассказывать друг другу, что такое интерпретатор, потому что у некоторых началась паника.
1 раунд
Ограничений нет. Фанового задания нет. Индивидуальных заданий нет. Населена роботами.
Тут ничего особенного не происходило, все расселись по командам и начали кодировать. Надо сказать, что почти все команды потратили большую часть отведенного времени, т.к. медленно въезжали, учили младших, утро, да и вообще, пинг большой и мама позвала. Но в итоге все справились (кто-то даже умудрился автоматически прогнать заготовленные нами тесты, что было делать совершенно не обязательно), и отправились кушать бутерброды.
2 раунд.
Ограничение: не использовать символы H, Q, 9, + в исходном коде программы. Фановое задание: на фоне играет музыка, меняться надо не раз в 11 минут, а на каждую песню. Индивидуальные ограничения есть (во всех последующих раундах тоже).
Все стало веселее. Возможность повторно использовать код не сильно помогала, т.к. ты попадал за новый компьютер, код видел в первый раз, а зачастую даже не умел программировать на том языке, на котором там писали. Но все равно очень мало кто писал код заново, все старались как-нибудь приспособиться к уже написанному. Самым забавным в этом смысле был код с паттернами, который кто-то умудрился написать в первом раунде. Это был единственный случай, когда другим командам, садившимся за этот компьютер, было действительно удобно.
Ограничение оказалось намного интереснее, чем мы планировали. Невозможность использовать строковые литералы с буквами H, Q, 9, + заставляла выносить все строки в файлы или использовать ASCII-коды. Невозможность использовать while, then (для паскаля), throw, catch, делало процесс кодирования намного веселее, чем в 1 раунде, хотя когда мы придумали 2 раунд, он нам показался не очень сложным.
Музыка доставляла. Плейлист был подобран таким образом, чтобы приносить максимальное количество фана, отвлекая только иногда. Надо сказать, что участники нам попались стойкими, ни Ранетки, ни Киркоров, их не проняли. Все сосредоточенно кодировали.
Индивидуальные задания тоже прошли отличненько. Самые интересные из них:
- Кодер использует только клавиатуру, а навигатор – только мышь.
- В качестве идентификаторов использовать только кошерные названия.
var cashrut = new StreatReader("input.txt"); string halacha = ""; string jewish; // List<int> rennet = new List<int>(); while ((jewish = cashrut.ReadLine()) != "" && jewish != null) { halacha = String.Concat(halacha, jewish); } List<int> curds = new List<int>(); while (curds.Count != 99) curds.Add(0); var birdsOfPrey = new StreamWriter("output.txt"); int rennet=halacha.Count(p => p == '+'); foreach (char clovenHoof in halacha) {
- Писать код одним пальцем.
- Писать код со включенным капсом.
В итоге, индивидуальные задания сильно не мешали, но добавляли веселья как самим участникам, так и окружающим. А вообще, это задание тоже выполнили почти все. И, как всегда, еда.
3 раунд
Ограничение: не использовать арифметические операторы (в т.ч. битовые) и операторы сравнения. Фановое задание: участники по очереди пишут сказку про программиста на Code Retreat.
Ограничение оказалось не таким сложным, как мы предполагали. Мы думали, все кинутся писать длинное сложение, а не тут-то было. В итоге, решения было 3: аппендить в строку и брать Length, складывать с помощью .NET Expressions, считать количество символов «+» во входном файле с помощью расширения Count из LINQ (не очень честное решение, но тесты проходит, да и нам очень понравилось).
Сказка получилась трешовой. Какая-то смесь философии, дзена и безысходности. Потом наберем и выложим.
Из забавных индивидуальных ограничений в этом раунде запомнилось только «При каждом успешном билде кричать «НЯ!» и танцевать танец маленьких утят». Зато развеселило оно не только саму команду, но и всех вокруг.
Еда.
4 раунд
Ограничение: не использовать циклы, goto и коллекции (за исключением строк). Фановое задание: нет.
Основной идеей было натолкнуть ребят на использование рекурсии. Строки были разрешены только для упрощения работы со строковыми литералами (чтобы не читать каждый раз строку из файла, т.к. в рекурсивном варианте это вообще какой-то треш). В итоге из-за этой поблажки прошло забавное решение на String.Replace, но мы не переживаем, оно нам тоже очень понравилось. До рекурсии дошли почти все команды, причем некоторые за половину времени, им мы предлагали решить проблему stack overflow на очень большой последовательности команд. Тут нужно было дойти до идеи использования новых потоков или даже процессов при достижении большой глубины стека, и некоторые даже придумали это решение, но на реализацию времени никому так и не хватило.
Фановое задание на этот раунд мы добавлять не стали, т.к. считали, что основное ограничение и без того сложное. В итоге, с этим раундом участники справились в среднем даже быстрее, чем с предыдущими, видимо раскачались за 4 часа.
Интересные индивидуальные ограничения:
- Навигатор завязывает глаза.
- Использовать только «_» для идентификаторов.
case '9': { var __________ = new StreamReader("lyrics.txt"); string _________ = __________.ReadToEnd(); __________.Close(); ________.WriteLine(_________); break; } } if (_.Length == 1) return ______; else { _ = _.Remove(0, 1); ______=__(_, ___, ______); return ______; } }
- Идентификаторы на китайском.
static void Main(string[] args) { 輸入 = File.ReadAllText("input.txt"); FileStream 作為故事講述 = new FileStream("output.txt", FileMode.Create); FileStream 用故事畫裝飾 = new FileStream("counter.txt", FileMode.Create); 閱讀 = new StreamWriter(作為故事講述); StreamWriter 他編造了他的學歷經歷 = new StreamWriter(用故事畫裝飾); 表(輸入); 他編造了他的學歷經歷.Write(計數器); 他編造了他的學歷經歷.Close(); 閱讀.Close(); }
- Не использовать пробелы и табуляцию.
private static void ReadSymbol(in i) { char[] c=new char[1]; if(file.Read(c,i,1)<=0) return; i++; switch(c[0]) { case 'H':file1.WriteLine("Hello,world!");break; case 'Q':file1.WriteLine(file);break; case '9':file1.WriteLine(stih);break; case '+':count++;break; } } } }
Конец. Уборка. Валим.
Мероприятие получилось очень веселым и не сильно сложным. 16 участников (со всех курсов, с 1 бакалавриата по 2 магистратуры), 8 организаторов, куча еды, 5 часов кодинга, 3 языка программирования (Object Pascal, C#, C++). Все довольны, мы тоже. Будем проводить еще. Программируйте больше и с удовольствием!
Автор: homax