Создайте интерпретатор для поддельного стекового языка, который получает входные данные, интерпретирует их и выводит результат в виде массива чисел. Он должен перебирать каждый байт и выполнять разные функции на основе этой таблицы:
0000 (0): объединить (объединить два верхних числа в стеке, как если бы они были строкой. Например: 12,5 -> 125)
0001 (1): приращение (добавить 1 к числу на вершине стека)
0010 (2): Уменьшение (вычесть одно из числа в верхней части стека)
0011 (3): Умножить (Умножить два верхних числа в стеке)
0100 (4): Разделить (Разделить 2-е число на верхнее верхнее число в стеке)
0101 (5): сложение (добавление двух верхних чисел в стеке)
0110 (6): вычитание (вычитание верхнего числа в стеке из числа ниже)
0111 (7): экспонента ( Вычислите число от второго до верхнего в степени старшего числа)
1000 (8): Модуль: (Найти число от второго до верхнего по модулю верхнего)
1001 (9): повернуть вправо (сдвинуть стопку на единицу. Число внизу вверху)
1010 (A): повернуть влево (сдвинуть стопку вверх. Число вверху теперь внизу)
1011 (B): Дублировать (Скопировать верхнее число, чтобы оно появилось дважды. Например: 4,1 становится 4,1,1)
1100 (C): Двойное дублирование (Скопировать два верхних числа в стеке. Пример: 4, 1,2 становится 4,1,2,1,2)
1101 (D): поменять местами ( поменять местами два старших числа в стеке, например: 4,1,2 становится 4,2,1)
1110 (E): удвоить Поменять местами (Поменять местами два верхних числа с двумя ниже них. Например: 1,2,3,4,5 становится 1,4,5,2,3)
1111 (F): Удалить / Выскочить (Удалить число вверху стек)
Например, файл, содержащий
1 1 BC 5 C 5 B 9 5 - Вход (шестнадцатеричный) | | | | | | | | | | 1 2 2 2 4 4 6 6 2 8 - Стек 2 2 2 2 4 6 6 6 2 2 4 2 4 6 4 2 2 2 2 4 2 2 2 2
выдаст [8,6,4,2]
Правила:
- Юникод / символы в порядке, но ASCII лучше.
- Будь креативным! Короткость имеет значение, но креативность велика!
- Если байты слишком жесткие, используйте
"$iv*/+-^%><dtsz."
или"0123456789ABCDEF"
вместо реальных байтов. - SPEED! Чем быстрее тем лучше.
- Оценка основана на репутации, но размер является огромным фактором.
Бонус:
Попробуйте выполнить эту задачу, используя только что созданного вами переводчика, как можно короче.
Замечания:
В отличие от других задач, связанных с программированием, это усложняет то, что нет никакого кода, который можно было бы решить. Если, скажем, вам пришлось написать интерпретатор brainf * ck, вы могли бы взглянуть на реализации других людей. С этим вы не можете сделать это.
Я забыл поставить и дату окончания на этом. Я думаю, я сделаю это через месяц с момента, когда я создал это. Человек с наибольшим количеством голосов 22 февраля побеждает!
источник
Ответы:
Ruby, 67 строк регулярных выражений
Я решил написать интерпретатор в регулярных выражениях, придерживаясь при этом эффективных алгоритмов.
Я мог бы использовать простые байты, но, по моему мнению, использование символов делает код более читабельным. Конечно, если бы мы могли упаковать две инструкции в один байт ...
Конкатенация отрицательных значений приводит к поведению дополнения к десяти, отражающему внутреннее представление.
Деление - это целочисленное деление, а остаток никогда не бывает отрицательным.
Что касается бонусного раунда, то самое короткое решение ( 13 символов ) - это чистое решение:
источник
d
(после тогоii
, как в стеке есть только2
своп, нечего менять), а финальная вращается (ну, по крайней мере, первая, вторая - просто замаскированный своп ... ) должно быть слева, а не справа.сборка x86 (на Win32)
«СКОРОСТЬ!» Здесь очень важно, и мы все знаем, что в этом отношении ничто не сравнится с языком ассемблера. Итак, давайте сделаем это в сборке!
Это реализация языка ассемблера x86 (в синтаксисе NASM), в котором числа хранятся и интерпретируются как 32-разрядные целые числа без знака, напрямую используя собственный стек x86. Переполнение стека и переполнение во время любой арифметической операции (или деление на ноль) - это ошибка времени выполнения, завершающая программу сообщением об ошибке.
Чтобы скомпилировать это, используйте что-то вроде
Программа получает имя двоичного файла, содержащего программу, в командной строке (например
nexlang.exe testprg.bin
). По окончании он выводит конечное содержимое стека на стандартный вывод в удобочитаемом формате.Чтобы помочь с тестированием, сохраните следующее в
nex.def
:А затем напишите свои программы NEX («несуществующие», как указано в названии вопроса), используя вышеуказанную мнемонику, и скомпилируйте что-то вроде
Например, для исходного теста используйте следующее
prg.nex
:И, наконец, для задачи «2014» используйте следующую 14-байтовую программу NEX:
источник
LEA ESI, [ESI+1]
а неINC ESI
?GolfScript, 64 символа
Хорошо, поэтому я решил попробовать это в гольф. А какой язык для игры в гольф лучше, чем GolfScript?
Удобно, что сам GolfScript уже является стековым языком с однобайтовыми командами, и, как это бывает, 11 из ваших 16 команд отображаются непосредственно на встроенные команды GolfScript. Поэтому все, что мне действительно нужно сделать для интерпретации вашего языка, - это реализовать оставшиеся пять команд в GolfScript и построить таблицу перевода:
Код выглядит немного растянутым, потому что я использую переводы строк в качестве разделителей для таблицы перевода. Инициал
0\
помещает ноль в стек и перемещает его ниже входной программы.{ }/
Цикл, включающий большую часть кода, принимает программу ввода из стека и перебирает тело цикла над каждым из его символов, и окончательный]-1%`
собирает стек в массив, изменяет его (потому что ваш образец начинает вывод из верхней части стек) и упорядочивает его.Тело цикла начинается с строки в 16 одинарных кавычках.
n%
разбивает эту строку на разрывы строк,=
ищет подстроку, соответствующую вводимому символу, и~
оценивает подстроку как код GolfScript.Наконец, вот реализация GolfScript из 16 команд:
`+~
: объединить два числа в виде строк)
: приращение(
: уменьшение*
: умножить/
: разделить+
: добавить-
: вычесть?
: поднять к власти%
: модуль](+~
: повернуть стопку вправо])\~
: повернуть стопку влево.
: дубликат1$1$
: двойной дубликат\
: своп[@]\+~\
: двойной своп;
: попЯ немного недоволен двойным обменом - он уродлив и намного дольше, чем любая другая команда. Такое ощущение, что должен быть лучший путь, но если так, я еще не нашел его. Тем не менее, по крайней мере, это работает.
Например, запустив указанную выше программу для ввода (заданного в виде строки в двойных кавычках GolfScript / Ruby / Perl / Python / и т. Д.):
дает выход:
Изменить: мне удалось сохранить еще два символа, в общей сложности 62 символа , используя более компактную кодировку таблицы перевода. Тем не менее, это отчасти жертвует читабельностью:
Примечательные особенности этой версии включают
(
в начале цикла, который сдвигает индексы команд от 0..15 до -1..14, так что я могу поместить длинную последовательность односимвольных команд от 1 до 8 в начале стола. Это позволяет мне хранить их в отдельной строке и исключать восемь новых строк, разделяющих их; увы, дополнительная сложность стоит мне шесть символов в другом месте.источник
+
в])\+~
Haskell
Просто для забавы я сделал решение, которое не использует никаких переменных , а только объединяет функции вместе.
источник
Рубин,
330316 символовЯ решил сыграть в гольф. (Потому что это всегда весело.)
Основная часть такова:
Он переводит каждую шестнадцатеричную цифру в целое число-10, а затем использует
[(huge array of strings)]
строку, чтобы найти правильную строку, которая представляет эту команду. Тогда этоeval
та строка.Обратите внимание, что
%w[x y z]
эквивалентно['x','y','z']
.Мне также нравится, как вы можете найти улыбающиеся лица в этой строке! Некоторые из них
:*
:/
:-]
:%
Образец прогона:
источник
C -
642634 знакаТолько для
$iv*/+-^%><dtsz.
диалекта (добавляетсяq
как конечный символ вместе с0
):Решение для 2014 вызова:
dididiizs>
.источник
free(a);
. И разве не должно быть<<2
вrealloc
звонках?free()
памяти: Pк, 228
Существует довольно много повторений в реализации подобных инструкций, которые, вероятно, могут быть в некоторой степени устранены.
источник
С
+924+882622603587569562 символаС удаленными очевидными переводами строки (сохранено для удобства чтения).
Это реализует интерпретацию «недопущение толкает ноль» из комментария Яна Дворжака.
Версия для игры в гольф на самом деле существенно изменилась по сравнению с версией без игры в гольф под (добрым) давлением хорошего ответа Оберона .
Я обнаружил, что замена
switch
заявления в пользу цепочкиif
...else
позволила мне исключить все цифры из моих дел . Вместо этого он инициализируетw
переменную до 47, поэтому один шаг увеличивает ее до 48 (== ascii'0'
), затем каждый случай увеличиваетсяw
до тех пор, пока нам не придется переходить к'A'
точке, в которой мы используем в основном пустой первый аргумент макроса, который добавляет дополнительные 7, чтобы получить на «А». Ungolfed версия действительно показывает мой любимыйsbrk
/SIGSEGV
трюк , чтобы получить «бесплатно» память без каких - либо дополнительных ассигнований.источник
log
это даже не определено.R, 428 символов
С отступами:
В бою:
источник
JavaScript, 685
Версия без гольфа ( суть ):
Гольф версия:
Пример:
источник
Haskell
Бег
источник
tr
?), То это станет возможным.Common Lisp - 589
Принимает шестнадцатеричный ввод без пробелов.
Ungolfed:
источник
PHP
это не самый красивый, но это работает.
запускается из оболочки, ожидает имя файла в качестве первого аргумента. он принимает любой из 3 диалектов (даже смешанный)
поведение не определено для негативов или отсутствующего индекса
источник
PureBasic -
2821891 символЭто интерактивный интерпретатор - нет файла, вы просто вводите коды, заданные 0-9, AF, и он выполнит эту команду и отобразит ее в виде сообщения, приведенного в примере.
Используйте «X» или «Q», чтобы выйти.
Это было действительно весело делать :)
редактировать: после сна я решил играть в гольф - я оставил читабельную версию, хотя для справки.
Все работает так же, за исключением того, что я вынул Q или X, чтобы выйти, просто закройте окно, чтобы выйти:
источник
Common Lisp - 586
Ungolfed
Лексически связывает новый стек в макрорасширенном коде: нет ссылки на глобальную переменную. Кроме того, он скомпилирован в машинный код.
пример
источник
Python 2, 508 байт
Использует кодировку "0123456789ABCDEF". Я действительно горжусь тем, как это получилось. Он не читает файл, он получает данные из STDIN, но если это проблема, ее можно легко изменить.
2 решения проблемы 2014 года:
B11CB3A1AED0A00
(1615 байт) - общий конкатенатор.BB102CD11B513B3622E
(2019 байт) - намного круче - оценивает в (5 * (10-1)) ^ 2-11источник
Python 2, 955 байт
Что делает каждая функция
источник