Описание
Воображаемый язык программирования (IPL) использует польскую обратную нотацию. У него есть следующие команды:
- я - введите число и поместите его в стек
- o - неразрушающий вывод вершины стека (число остается в стеке)
- d - сбросить вершину стека
- целое число - поместите этот номер в стек
- + - * - вытолкнуть два числа из стека, выполнить соответствующую операцию и вернуть результат обратно. В IPL нет разделения.
IPL работает только с целыми числами и используется для простых вычислений. Программа IPL написана в одну строку и разделена пробелами. Пустая строка является допустимой программой IPL.
Программа IPL:
i i + o
Вводит два числа, складывает их вместе и выводит результат.
Входные числа и целые числа, которые можно поместить в стек, находятся в диапазоне [-999, 999], однако выходные данные могут быть любыми. Если ваш язык не поддерживает большие цифры, это нормально.
Формат ввода / вывода
Вы можете выбрать любой формат ввода / вывода, если он понятен для чтения и чтения / записи: строка, список, токены и т. Д.
задача
Вам дана некоторая программа IPL, вам нужно ее оптимизировать (уменьшить длину):
i 12 + 3 + o d 2 3 + d
После оптимизации станет
i 15 + o
Вам не нужно сохранять состояние стека, но количество входов и выходов и их порядок должны соответствовать исходной и оптимизированной программе.
Итак, программа IPL:
-40 i * 2 * o i + 3 1 + o i 2 *
После оптимизации станет
i -80 * o i 4 o i
или
-80 i * o i 4 o i
(обратите внимание, что вы должны сохранить все входные данные, даже если они не имеют значения).
Для тестовых случаев не должно быть жесткого кодирования, код должен работать в любой произвольной программе IPL и создавать максимально короткую программу IPL, отвечающую требованиям.
счет
Код по умолчанию - оценка игры в гольф.
ОБНОВЛЕНИЕ: изменено начисление баллов на чистое, в соответствии с предложением @Sanchises.
Тестовые случаи:
Входные данные:
(empty string)
Возможный вывод:
(empty string)
Входные данные:
i 4 * 2 + 3 * 6 - o
Возможный вывод:
i 12 * o
Входные данные:
1 1 + o
Возможный вывод:
2 o
Входные данные:
i 2 + 3 + o d 2 3 + d
Возможный вывод:
i 5 + o
Входные данные:
-40 i * 2 * o i + 3 1 + o i 2 *
Возможный вывод:
-80 i * o i 4 o i
Входные данные:
i i 1 + i 1 + i 1 + i 1 + d d d d o
Возможный вывод:
i i i i i d d d d o
Входные данные:
i i i 0 * * * o
Возможный вывод:
i i i 0 o
Входные данные:
i i i 1 * * * o
Возможный вывод:
i i i * * o
Входные данные:
i 222 + i 222 - + o
Возможный вывод:
i i + o
Входные данные:
i 2 + 3 * 2 + 3 * 2 + 3 * i * d i 2 + 3 * i + d i o 2 + 2 - 0 * 1 o
Возможный вывод:
i i i i i o 1 o
Входные данные:
i 1 + 2 * 1 + o
Возможный вывод:
i 2 * 3 + o
Входные данные:
1 1 + o i 2 + 3 + o d 2 3 + d 4 i * 2 * o i + 3 1 + o i 2 * i i 1 + i 1 + i 1 + i 1 + d d d d o i i i 0 * * * o i i i 1 * * * o i 2 + i 2 - + o i 2 + 3 * 2 + 3 * 2 + 3 * i * d i 2 + 3 * i + d i o 2 + 2 - 0 * 1 o
Возможный вывод:
2 o i 5 + o 8 i * o i 4 o i i i i i i d d d d o i i i 0 o i i i * * * o i i + o i i i i i o 1 o
источник
i i d o
доi o i
(вход в порядке, а выход в порядке) или вы не должны упростить его? (набор входов и выходов должен быть в порядке)Ответы:
Wolfram Language (Mathematica) ,
733728690564516506513548 байтПопробуйте онлайн!
Это четырехэтапная демонстрация силы, которая (1) заменяет «-» на «-1 * +», чтобы нам не приходилось иметь дело с вычитаниями, (2) немного упрощает список команд, ( 3) составляет список всех перестановок в этом списке команд и выбирает те, которые дают одинаковый результат при разборе (выполнении), и (4) немного упрощает эти списки команд и выбирает самые короткие после преобразования определенных операций обратно в вычитания.
Этот код ужасно неэффективен, потому что он проходит через список всех перестановок входного кода. Для длинных входных кодов я не рекомендую запускать этот код; но, как я читаю, в этом вызове нет никаких ограничений времени выполнения или памяти.
Этот код выполняет шаг оптимизации после преобразования всех операций «-» в операции «+» с перевернутыми знаками, и только в конце вновь вводит оператор «-» при преобразовании кода обратно в строки. Это подразумевает, например, что «i -1 i * + o» правильно оптимизирован до «ii - o».
Так как требования к формату ввода / вывода довольно просты, этот код принимает и возвращает код в виде списков, где символы «+», «-», «*» представлены символами p, m, t, соответственно. Преобразование из и в строки выполняется в функции-обёртке, заданной для TIO:
Версия без игры в гольф, включая оболочку строкового формата и минимизацию конечной длины строки кода вместо количества токенов, а также несколько дополнительных тонкостей преобразования:
Спасибо @redundancy за обнаружение ошибки: парсер нуждается в
Expand
применить к выводу для обработки дистрибутивной эквивалентности. 506 → 513Обновить
Теперь также оптимизирует
1 o 1 + o
к1 o 2 o
. Это был удивительно сложный случай, и код стал намного медленнее. 513 → 548источник
i i 1 + i 1 + i 1 + i 1 + d d d d o
.i 2 * i 2 * + o
должен производить оптимизированный выводi i + 2 * o
, но этот код возвращает (неоптимизированный) ввод.