Starry - забавный эзотерический язык программирования, в котором код состоит только из того, +*.,`'
где фактическая команда, представленная каждым из этих символов, определяется количеством пробелов перед ним. Это делает его сложным даже для задач с фиксированным выходом, потому что разные команды могут учитывать разное количество байтов. В частности, числовые литералы имеют унарное представление, что делает необходимым создание больших чисел, оперируя меньшими.
Поэтому задача состоит в том, чтобы написать программу, способную играть в такие звездные программы.
Как работает Starry?
(В esolangs некоторые детали не указаны, поэтому я собираюсь рассказать о поведении интерпретатора Ruby .)
Starry - это основанный на стеке язык с одним стеком целочисленных значений произвольной точности (который изначально пуст).
Единственные значимые символы:
+*.,`'
и пробелы. Все остальные символы игнорируются. Каждая последовательность пробелов, за которой следует один из этих непробельных символов, представляет собой одну инструкцию. Тип инструкции зависит от непробельного символа и количества пробелов.
Инструкции:
Spaces Symbol Meaning
0 + Invalid opcode.
1 + Duplicate top of stack.
2 + Swap top 2 stack elements.
3 + Rotate top 3 stack elements. That is, send the top stack element
two positions down. [... 1 2 3] becomes [... 3 1 2].
4 + Pop and discard top of stack.
n ≥ 5 + Push n − 5 to stack.
0 mod 5 * Pop y, pop x, push x + y.
1 mod 5 * Pop y, pop x, push x − y.
2 mod 5 * Pop y, pop x, push x * y.
3 mod 5 * Pop y, pop x, push x / y, rounded towards -∞.
4 mod 5 * Pop y, pop x, push x % y. The sign of the result matches the sign of y.
0 mod 2 . Pop a value and print it as a decimal number.
1 mod 2 . Pop a value and print it as an ASCII character. This throws an error
if the value is not in the range [0, 255].
n ` Mark label n.
n ' Pop a value; if non-zero, jump to label n.
Обратите внимание, что интерпретатор сканирует исходный код для меток перед началом выполнения, поэтому можно переходить как вперед, так и назад.
Конечно, у Starry также есть команды ввода (использующие ,
аналогично .
), но они не имеют отношения к этой задаче.
Соревнование
Получив строку, сгенерируйте программу Starry, которая не принимает ввод и печатает эту строку точно в STDOUT.
Вы можете написать программу или функцию, принимая ввод через STDIN (или ближайшую альтернативу), аргумент командной строки или аргумент функции и выводя результат через STDOUT (или ближайшую альтернативу), возвращаемое значение функции или параметр функции (out).
Вы можете предположить, что строка не длиннее 128 символов и будет состоять только из печатных символов ASCII (кодовые точки от 0x20 до 0x7E).
Ваше решение должно обрабатывать любой такой ввод менее чем за 5 минут на подходящем настольном компьютере (есть некоторая свобода в этом; если на моем ноутбуке это займет несколько минут, я не против, но если это займет 15, я дисквалифицирую Это).
Ваше решение будет проверено на ряде различных строк, перечисленных ниже. Ваша оценка - это общее количество байт соответствующих программ Starry. В случае ничьей побеждает самый короткий метагольфер. То есть, не пытайтесь играть в свой собственный код, если нет ничьей (что, я думаю, произойдет только в том случае, если возможно оптимальное решение).
Вы не должны оптимизировать свой код под конкретные тестовые примеры, перечисленные ниже. В частности, вы не должны жестко кодировать для них решения, изготовленные вручную. Оптимизация под классы строк, структура которых аналогична структуре данных строк, это хорошо. Если я подозреваю кого-либо в решениях с жестким кодированием, я оставляю за собой право заменить некоторые или все тестовые случаи (на строки сопоставимых структур).
Тестовые случаи
Каждая строка представляет собой отдельный контрольный пример:
Hello, World!
pneumonoultramicroscopicsilicovolcanoconiosis
.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.
Hickory, dickory, dock. The mouse ran up the clock. The clock struck 1. The mouse ran down. Hickory, dickory, dock.
36912059868043514648560046917066768694455682545071266675083273015450033938555319356951628735735013250100789433961153496780296165
bVZ48121347GLtpYnt76CZSxTpMDs6791EJE808077eySXldY162424ddTB90707UupwlWGb63618542VhA252989453TXrWgqGm85899uHOAY2oAKE198GOVUttvW63
7MYxoWBNt180CDHS5xBGvU70HHVB17bh8jYzIIiU6n6g98Rose1nOe8Svcg56nax20q30kT3Ttb2jHl5q2Iuf1vPbjPxm9cyKXwxc0OUK8pr13b2n7U9Y7RwQTc26A1I
n9}unwxVa}[rj+5em6K#-H@= p^X/:DS]b*Jv/_x4.a5vT/So2R`yKy=in7-15B=g _BD`Bw=Z`Br;UwwF[{q]cS|&i;Gn4)q=`!G]8"eFP`Mn:zt-#mfCV2AL2^fL"A
Кредиты для второго контрольного теста идут к Деннису . Кредиты для четвертого теста идут на Sp3000.
Эталонное решение
Вот действительно базовое справочное решение в CJam:
q{S5*\iS*'+S'.}%
Вы можете запустить его для всего набора тестов здесь. Баллы:
1233
5240
4223
11110
7735
10497
11524
11392
Total: 62954
Это самый простой подход: выдвинуть кодовую точку каждого символа как литерал, а затем распечатать его. Здесь не используются небольшие различия между последовательными символами, целочисленной печатью, повторяющимися частями строки и т. Д. Я оставлю эти вещи вам.
Я считаю, что есть много возможностей для улучшения. Для справки, самое короткое ручной работы "Привет, мир!" всего 169 байт.