Конкурс окончен, смотрите результаты в конце вопроса.
Я думаю, многие из вас видели вопросы, состоящие из просьбы перевода программы с одного языка на другой. Давайте-ка покажем, как делать такие вещи правильно! В нашем конкурсе мы исходим из такой простой программы на Паскале: program test var a, b, c: integer begin readln(a) readln(b) c := a + b writeln(c) end. (Она же на ideone.) Задание состоит в следующем: вы должны перевести программу на любой-язык так, чтобы сохранить как можно больше от исходного текста программы. В качестве целевого языка, понятно, исключаются языки группы Паскаля (Delphi, Algol, Oberon, Modula, etc., все языки, в которых используется begin/end для группировки команд в составную команду). Вы можете дописывать конструкции до и после данного в условии текста, но не внутри его (точнее, можете и внутри, но это будет считаться изменением — смотрите ниже условия подсчёта). Сам текст желательно менять как можно меньше. Ограничения: Строки исходной программы между begin и end должны сохранять свой смысл. Они должны выполняться, и при их выполнении должно происходить в общих чертах то же, что и в исходной программе: readln должно считывать значения с консоли, c := a + b должно складывать значения двух переменных (или что там есть в вашем языке) в третью, writeln должно выводить правильный результат на консоль. (Это означает, что вы не можете просто закомментировать код первоначальной программы.) Определение победителя: Выигрывает код, в котором исходный текст менее всего изменён по сравнению с полным первоначальным вариантом (количество добавленных символов + количество удалённых символов + количество изменённых символов), считая и строки с program и end.. Разница в больших/маленьких буквах, а также замена символа на одинаковый по начертанию (например, русское «с»/английское «c») считается за пол-символа. Если два решения имеют одинаковое количество отличий (например, ноль), выигрывает то, у которого меньше добавленного кода (в символах). Если несколько решений одинаковы и по этому критерию, выигрывает то решение, которое получит больше голосов (как обычно, «за» минус «против»). В частности, полное совпадение кода выигрывает у неполного независимо от количества подготовительного кода. Для того, чтобы было легче проверять ваш код, старайтесь публиковать ссылку на онлайн-компилятор с вашим кодом. Код должен компилироваться без ошибок (пусть даже с предупреждениями) и правильно работать в диапазоне входных чисел от 0 до 1000. Продолжительность конкурса — 1 неделя.
Для исключения разночтений, при неясности в правилах пожалуйста переспрашивайте в комментариях или в чате, посвящённом code golf.
Для примера, вот внеконкурсное решение на plain TeX:
ewcount\tmp ewcount\c \def\uncatcodeletters{\uncatcoderange{`a}{`z}\uncatcoderange{`A}{`Z}} \def\uncatcoderange#1#2{% \tmp=#1 \advance\tmp -1 \loop\advance\tmp 1 \expandafter\catcode umber\tmp=11 \ifnum\tmp<#2 <br>epeat} \def\s{\begingroup\uncatcodeletters\shlp} {\def~ := #1 + #2 {% \global\expandafter\c\csname #1\endcsname \global\expandafter\advance\expandafter\c\csname #2\endcsname \endgroup} \global\let\shlp=~} \def\inp{\begingroup\uncatcodeletters\inphelper} \def\inphelper eadln(#1) {\endlinechar=-1 \escapechar=-1 \expandafter\inphelperi\csname #1\endcsname\endgroup} \def\inphelperi{\global ead16 to } \def\out{\begingroup\uncatcodeletters\outhelper} \def\outhelper riteln(#1) {\message{\expandafter\the\csname #1\endcsname}\endgroup} \let\DEF\def \let\END\end \catcode`r=13 \let r=\inp \catcode`w=13 \let w=\out \catcode`p=14 \catcode`v=14 \catcode`b=14 \let~=\catcode ~`c=13 \let c=\s ~`e=13 \DEF end.{\END} program test var a, b, c: integer begin readln(a) readln(b) c := a + b writeln(c) end. (Если кому интересно, гольфированный вариант.) Транскрипт компиляции: ~>tex golf.tex This is TeX, Version 3.14159265 (MiKTeX 2.9 64-bit) (golf.tex a=5 % <-- 5 введено с консоли<br>b=8 % <-- 8 введено с консоли 13 ) No pages of output. Transcript written on golf.log. <br> Просьба к отвечающим писать в начале решения ваш язык, количество изменённых символов и количество символов в подготовительном коде. Также просьба давать не более одного решения на ответ.
Обновление: Конкурс окончен, вот результаты. Побеждает ответ @Mike, сумевший уложиться в 78 подготовительных символов, и не поменять ни символа в исходном коде. Другой ответ того же автора выглядит чрезвычайно изящно (подключение паскалевского синтаксиса как внешний модуль, хей!), и почти выиграл приз зрительских симпатий, но проигрывает по количеству символов вследствие своей большей общности. Оба решения пользуются особенностью языка Perl, который в своих модулях позволяет предобработку текста на Perl самим Perl'ом. Мощный язык, мощные средства управления синтаксисом, заслуженная победа. Второй в списке победителей — ответ @Qwertiy. Это решение продолжает идею «получить текст как строку, обработать, чтобы получился код на нужном языке, и выполнить над ней eval», с симпатичной, очень техничной и компактной реализацией (регулярки!). Приз зрительских симпатий получает неожиданный ответ @kmv. В этом решении текст исходной программы не объявляется строкой, а «вытягивается» из кода функции! (Это, формально говоря, решение не по стандарту, но фактически в распространённых браузерах toString() работает именно так.) Третье место получает решение @pavel с комбинацией Unix shell/C, которое обходится без eval за счёт замены строк до компиляции и использования препроцессора C. Такой подход позволяет справиться с двоеточиями, которые вызывают затруднения для препроцессора у чистых решений на C/C++. Вообще, идея со строкой и eval оказалась наиболее популярной, её реализуют также ответы @edem Perl, построчная замена, практически интерпретация, @Red Skotina (замена строк на Питоне, построчная адаптация текста, оставаясь в рамках правил, хотя и на грани), @gil9red (то же, но более универсально, Питон), @nuts119 на C# (да, в C# можно сделать eval, вы не знали?) и @Streletz на Java (интерпретатор из сторонней библиотеки). Тему интерпретации продолжает ещё одно решение @nuts119 на C# с использованием DataTable как arithmetic engine. Это решение, при всей его сложности, имеет дальний прицел на построение полноценного интерпретатора. Оставшиеся решения на чистом C/C++ и Javascript/Typescript без eval вынуждены модифицировать исходный текст, хотя они смогли обойтись минимальным количеством изменений. Из этих решений наилучшие с одним удалённым символом решения @kmv (C, препроцессор, использование битовых полей) и @Qwertiy (C++, тонкости препроцессора). Интересно, что эти оба решения убирают из исходного текста соседние символы: из := убрано в первом случае двоеточие, а во втором — знак = (!). Оставшиеся четыре решения (@Qwertiy, typescript, @pavel, C++, препроцессор (заработало больше голосов, чем победитель), снова @Qwertiy, javascript и @Grundy, C, препроцессор) меняют больше символов в исходном коде, но также интересны и стоят вашего внимания. Большое спасибо всем, кто принимал участие в конкурсе!
Таблица лидеров: (спасибо @Grundy за адаптацию скрипта и @jfs за идею)
Ответ Раз в конкурсе участвует размер, вот еще вариант (лично мне нравится меньше, потому как большая ориентировка именно на этот код): perl, подготовка 97, измененных 0 perl, подготовка 78, измененных 0 sub r{$_[0]=<>} sub wr{print@_} $_=q. program test var a, b, c: integer begin readln(a) readln(b) c := a + b writeln(c) end. s/\b(\w)\b/\$$1/g s/^\S.*|.{4}n|://gm eval Тест на ideone В коде происходит: Создаем функции r/wr аналогичные по действию паскалевским read/write ln. $_=q. присваивает "переменной по умолчанию" весь текст до следующего знака .. Все последующие строки работают с этой "переменной по умолчанию", так как явных переменных в них не указано. Перед переменными (однобуквенными словами) ставим знак $. Удаляем строки program, var, begin, end, части названий функций (readln=r, writeln=wr), двоеточия Выполняем полученный текст: r($a) r($b) $c = $a + $b wr($c)