Quylthulg - это язык Криса Пресси, который пытается решить проблему инфиксной нотации, используя то, что он называет panfix :
подобно postfix, panfix не требует развертывания тайных изобретений, таких как скобки, чтобы переопределить приоритет оператора по умолчанию. В то же время panfix позволяет указывать термины в том же порядке и порядке, что и infix, что, несомненно, является естественным и интуитивно понятным обозначением для тех, кто привык к нему.
Как вы получаете удобство инфиксной нотации наряду с однозначностью префикса или постфикса? Используйте все три, конечно!
=y=+*3*x*+1+=
Более формально, пусть +
будет оператором и a
и b
будет выражением. потом(a+b)
допустимое (заключенное в скобки) инфиксное выражение, панффиксное представление этого выражения +a+b+
, где сопоставление представляет конкатенацию.
Ваша цель - взять строку Panfix и преобразовать ее в полностью заключенный в скобки инфикс:
(y=((3*x)+1))
Для простоты мы внесем следующие изменения:
- Операторы могут состоять только из двух уникальных символов (вы можете выбрать любой, но здесь я буду использовать
*
и+
). - Существует только один литерал, который состоит из другого отдельного символа (вы можете выбрать любой, но здесь я буду использовать
_
). - На входе будет правильно сформированное выражение panfix.
Для сложности сделаем следующее изменение:
- Операторы могут состоять из любого положительного числа символов, а не только одного.
Это усложняет задачу, поскольку вы не можете точно определить, как данная подстрока символов оператора разделена, не глядя на остальную часть строки.
Вот эталонная реализация для вызова, любезно предоставленная @ user202729.
Тестовые случаи
format: input -> output
+*+_*+_*+++_+*+_*+_*+++ -> ((_*+_)+(_+(_*+_)))
**++*+***++_+_++_+*++*+***_*++*+*****_**_*_*** -> ((((_+_)+_)*++*+***_)*(_*(_*_)))
***_**_***_* -> ((_**_)*_)
+_+_+ -> (_+_)
*+*+++**+***+++++_*+*+++**+***+++++_*+*+++**+***+++++ -> (_*+*+++**+***+++++_)
*++++*+*_*_*+*+++****+_++****+_++****++*+*+++_*+++ -> (((_*_)+*+(_++****+_))*+++_)
+**+_*+_*+*_*+*_*+*_+*_+**+ -> (((_*+_)*_)+(_*(_+*_)))
+**+++++_+++++_+++++*_*+*+_++++++_+++++_+++++++* -> (((_+++++_)*_)+*(_+(_+++++_)))
+*+*+_+*+_+*+*_*+*_*+*+_+*+_+*+*+ -> (((_+*+_)*_)+(_*(_+*+_)))
**_**_**_*_****_* -> ((_*(_*(_*_)))*_)
Я использовал эту программу для генерации инфиксных строк для этой задачи (преобразование в panfix было тривиальным, но обратное - нет).
**_**_**_*_****_*
. Все ответы, которые я проверил, провалились.(_ + _)
?Ответы:
Пролог (SWI) ,
194163 байтаСохраняя колоссальные 31 байт, используя этот совет от 0 ' !
Оператор
^
принимает в качестве левого аргумента строку, содержащую выражение panfix, и устанавливает в качестве правого аргумента строку, содержащую соответствующее инфиксное выражение в скобках. Он используетx
в качестве буквального вместо_
.Попробуйте онлайн!
объяснение
Поскольку Пролог является декларативным языком, мы просто должны описать отношение между исправлением и выражением в скобках.
В объяснении используется эта слегка неутешительная версия:
Наше основное производство -
parenthesize
это выражение panfixX
в виде строки и отправка соответствующего инфиксного выраженияP
в скобках в виде строки. Он используетstring_chars
для преобразования входной строки в список символов, а затем просто передает егоexpr
.expr
берет список символовL
, анализирует первое найденное в нем выражение PanfixL
и отправляет эквивалент в скобкахX
и остаток списка символовR
. Есть два возможных вида выражений:L
-x
это выражение,x
а остаток - это все послеx
.O
(см.oper
Ниже); разобрать выражениеY
; разборO
снова; разобрать другое выражениеZ
; и разобратьO
в третий раз. Остальное все после третьего экземпляраO
. Выражение является результатом присоединенияY
,O
иZ
, в круглых скобках, в строку.oper
берет список символов, где первый символ,C
а остальныеT
; он анализирует оператор (т.е. набор из одного или нескольких символов оператора) и отправляет операторO
и оставшуюся часть списка символовR
. Чтобы сформировать оператор, символC
должен быть чем-то отличным отx
; также либоP
должен быть разборчив сT
, с остаткомR
; в данном случаеO
это конкатенацияC
иP
; или,O
это один символC
; в этом случаеR
справедливоT
.Работающий пример
Давайте возьмем вход
+*+x+x++*x+*
для примера.+*+x+x++*x+*
. Это не начинается сx
, поэтому мы анализируем оператор с самого начала.oper
будет анализировать как можно больше оператора, поэтому мы стараемся+*+
.x+x++*x+*
. Это должно бытьx
.+*+
, с+x++*x+*
. Однако это не удается .+*
вместо этого .+x+x++*x+*
. Это не начинается сx
, поэтому нам нужно проанализировать оператор.+
.x+x++*x+*
. Это должно бытьx
.+
снова разбор с+x++*x+*
.x++*x+*
. Это должно бытьx
.+
снова разбор++*x+*
.(x+x)
.+*
снова анализируем оператор из+*x+*
.x+*
. Это должно бытьx
.+*
снова разбор с+*
.((x+x)+*x)
.Поскольку больше не осталось символов, мы успешно перевели выражение.
источник
Perl,
7860585750 байтВключает
+1
в себяp
Использует
1
для+
и2
для*
(или фактически любая цифра работает для любого оператора)Для удобства тестирования по сравнению с приведенными примерами вы можете использовать это, которое делает переводы и удаление места для вас:
источник
Чистый ,
200192189 байтПопробуйте онлайн!
Определяет функцию
f
, принимаяString
и возвращая синглтон[String]
с результатом внутри.Некоторые аккуратные вещи:
_
источник
Сетчатка 0.8.2 , 138 байт
Попробуйте онлайн! Ссылка включает в себя более быстрые тестовые случаи. Объяснение: Движок регулярных выражений использует обратную трассировку для разделения строки на токены, которые затем добавляются или выталкиваются из
i
группы балансировки. Всегда выполняется хотя бы один оператор, помещенный в начале перед первой переменной. После переменной извлекается, по крайней мере, один оператор, и в этот момент запускается оператор с нажатием или другая переменная является допустимой. Операторы выталкиваются в группу в двух экземплярах, чтобы их можно было правильно высовывать. Пример:К сожалению, это не помогает нам зафиксировать результаты, чтобы заключить их в скобки, поэтому внешний оператор сопоставляется вручную. Квадратные скобки добавляются снаружи-внутрь, поэтому на первом этапе все выражения заключаются в квадратные скобки, а на последнем этапе они удаляются теперь, когда они распространяются до переменных.
источник
**_**_**_*_****_*
.Haskell ,
167166 байтПопробуйте онлайн! Пример использования:
head.e "**_**_**_*_****_*"
доходность((_*(_*(_*_)))*_)
. Все символы, кроме_
как интерпретируются как операторы,_
само по себе обозначает идентификатор.источник
Python 3, 226 байт
Определяет анонимную функцию с именем
R
.Попробуйте онлайн!
источник
_*+
; это было только то, что использовалось в примере. Возможно, вы сможете использовать это для игры в регулярные выражения (например,\d
вместо[*+]
).