Панфікс на зміну в дужках


16

Quylthulg - це мова Кріса Пресі, яка намагається вирішити проблему позначення інфіксації за допомогою того, що він називає panfix :

як postfix, panfix не вимагає розгортання прихованих накладів, таких як дужки, щоб замінити пріоритет оператора за замовчуванням. У той же час panfix дозволяє визначати терміни в тому ж порядку та порядку, що й інфікс, безперечно природних та інтуїтивних позначень для тих, хто до нього звик.


Як ви отримуєте зручність позначення інфіксу разом з однозначністю префікса чи постфікса? Використовуйте всі три, звичайно!

=y=+*3*x*+1+=

Більш формально, +будьте оператором, aі bбудьте виразами. Тоді (a+b)є дійсним (укрупненим у дужках) вираз інфіксування, представлення панфіксу цього виразу є +a+b+, де співставлення являє собою конкатенацію.

Ваша мета - взяти рядок panfix і перетворити його на повністю вкруглену посилання:

(y=((3*x)+1))

Для простоти внесемо такі зміни:

  • Оператори можуть складатися лише з двох унікальних символів (ви можете вибрати будь-якого, але тут я буду використовувати *і +).
  • Є лише один буквальний, який складається з іншого чіткого символу (ви можете вибрати будь-який, але тут я скористаюся _).
  • Введенням буде добре сформований вираз панфікса.

Для складності внесемо наступні зміни:

  • Оператори можуть складатися з будь-якої позитивної кількості символів, а не лише одного.

Це робить виклик більш складним, тому що ви не можете неодмінно визначити, як поділена дана підрядка символів оператора, не дивлячись на решту рядка.

Ось реалізація посилань на виклик, люб’язно надано @ user202729.

Випробування

format: input -> output
+*+_*+_*+++_+*+_*+_*+++ -> ((_*+_)+(_+(_*+_)))
**++*+***++_+_++_+*++*+***_*++*+*****_**_*_*** -> ((((_+_)+_)*++*+***_)*(_*(_*_)))
***_**_***_* -> ((_**_)*_)
+_+_+ -> (_+_)
*+*+++**+***+++++_*+*+++**+***+++++_*+*+++**+***+++++ -> (_*+*+++**+***+++++_)
*++++*+*_*_*+*+++****+_++****+_++****++*+*+++_*+++ -> (((_*_)+*+(_++****+_))*+++_)
+**+_*+_*+*_*+*_*+*_+*_+**+ -> (((_*+_)*_)+(_*(_+*_)))
+**+++++_+++++_+++++*_*+*+_++++++_+++++_+++++++* -> (((_+++++_)*_)+*(_+(_+++++_)))
+*+*+_+*+_+*+*_*+*_*+*+_+*+_+*+*+ -> (((_+*+_)*_)+(_*(_+*+_)))
**_**_**_*_****_* -> ((_*(_*(_*_)))*_)

Я використовував цю програму для генерування рядків інфіксації для цього виклику (перетворення на panfix було тривіальним, але реверсування - ні).




6
Схожий тест: **_**_**_*_****_*. Усі відповіді, які я перевірив, не вдалися до цього.
Нітродон

1
Чи можна мати додаткові пробіли у своєму виході, наприклад (_ + _)?
Тон Євангелія

2
@TonHospel Звичайно.
Esolanging Fruit

Відповіді:


6

Prolog (SWI) , 194 163 байти

Збережено колосальні 31 байт за допомогою цієї підказки від 0 ' !

[C|T]/O/R:-C\=x,(T/P/R,concat(C,P,O);O=C,R=T).
[x|R]-x-R.
L-X-R:-L/O/A,A-Y-B,B/O/C,C-Z-D,D/O/R,atomics_to_string(['(',Y,O,Z,')'],X).
X^P:-string_chars(X,L),L-P-[].

Оператор ^приймає за свій лівий аргумент рядок, що містить вираз panfix, і встановлює свій правий аргумент на рядок, що містить відповідний вираз у дужці. Він використовується xяк буквальний замість _.

Спробуйте в Інтернеті!

Пояснення

Оскільки Prolog є декларативною мовою, ми просто мусимо описати співвідношення між панфіксом та висловом у дужках.

У поясненні використовується ця злегка неозорена версія:

oper([C|T],O,R) :- C\=x, oper(T,P,R), concat(C,P,O).
oper([C|T],C,T).

expr([x|R],x,R).
expr(L,X,R) :- oper(L,O,A), expr(A,Y,B), oper(B,O,C), expr(C,Z,D), oper(D,O,R),
               atomics_to_string(['(',Y,O,Z,')'],X).

parenthesize(X,P) :- string_chars(X,L), expr(L,P,[]).

Основним нашим виробництвом є те parenthesize, що приймає вираз panfix Xяк рядок і висилає відповідний вираз Pу дужці як рядок. Він використовує string_charsдля перетворення вхідного рядка в список символів, а потім просто передає його в expr.

exprприймає список символів L, аналізує перший вираз панфікса, який він знаходить L, і висилає скобковий еквівалент 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).

Оскільки більше символів не залишилось, ми успішно перевели вираз.


4

Perl, 78 60 58 57 50 байт

Включає +1дляp

Використовує 1для +та 2для *(або фактично будь-яка цифра працює для будь-якого оператора)

perl -pe 's/\b((\d+)((?1)|_)\2((?3))\2)\b/($3 $2 $4)/&&redo' <<< 22_22_22_2_2222_2

Для зручного тестування порівняно з наведеними прикладами ви можете використовувати це, що робить переклади та видалення місця для вас:

perl -pe 'y/+*/12/;s/\b((\d+)((?1)|_)\2((?3))\2)\b/($3 $2 $4)/&&redo;y/ //d;y/12/+*/' <<< "**_**_**_*_****_*"

3

Чисто , 200 192 189 байт

import StdEnv,Text
f"_"=["_"]
f l=["("+a+p+b+")"\\p<-[l%(0,i)\\i<-[0..indexOf"_"l]|endsWith(l%(0,i))l],t<-[tl(init(split p l))],n<-indexList t,a<-f(join p(take n t))&b<-f(join p(drop n t))]

Спробуйте в Інтернеті!

Визначає функцію f, взяття Stringта повернення сингтона[String] з результатом всередині.

Деякі акуратні речі:

  • Не використовує регулярний вираз
  • Працює з будь-яким символом, крім операторів_

3

Сітківка 0,8.2 , 138 байт

.+
($&)
+`\((\d+)(_|((?<i>(?<i>\d+))|_(?<-i>\k<i>)+)+(?(i)(?!)))\1(_|((?<i>(?<i>\d+))|_(?<-i>\k<i>)+)+(?(i)(?!)))\1\)
(($2)$1($4))
\(_\)
_

Спробуйте в Інтернеті! Посилання включає більш швидкі тестові випадки. Пояснення: Двигун regex використовує зворотний трекінг для розділення рядка на лексеми, які потім висуваються або вискакують з iбалансуючої групи. Існує запуск завжди принаймні одного оператора, натиснутого на старті перед першою змінною. Після змінної вискакує щонайменше один оператор, у якому момент або запущений операторний запуск, або інша змінна є законним. Операторів підштовхують до групи у двох примірниках, щоб їх можна було правильно вискакувати. Приклад:

Input           Stack
Push *          * *
Push *++*+***   * * *++*+*** *++*+***
Push +          * * *++*+*** *++*+*** + +
Push +          * * *++*+*** *++*+*** + + + +
Variable _
Pop +           * * *++*+*** *++*+*** + + +
Variable _
Pop +           * * *++*+*** *++*+*** + +
Pop +           * * *++*+*** *++*+*** +
Variable _
Pop +           * * *++*+*** *++*+***
Pop *++*+***    * * *++*+***
Variable _
Pop *++*+***    * *
Pop *           *
Push *          * * *
Variable _
Pop *           * *
Push *          * * * *
Variable _
Pop *           * * *
Variable _
Pop *           * *
Pop *           *
Pop *

На жаль, це не допомагає нам фіксувати результати, щоб скористатися їх дужкою, тому зовнішній оператор узгоджується вручну. Дужки додаються назовні, тому перший етап обгортає весь вираз у дужках, а останній етап видаляє їх тепер, коли вони поширюються до змінних.


1
Це також не вдається **_**_**_*_****_*.
користувач202729

@ user202729 Працює зараз?
Ніл

@Neil Це працює зараз, так.
Οurous

1

Haskell , 167 166 байт

head.e
e('_':r)=["_",r]
e(x:r)=[x]%r
e _=[]
o%t@(c:r)|[x,u]<-e t,n<-length o,[y,v]<-e$drop n u,all((==o).take n)[u,v]=['(':x++o++y++")",drop n v]|p<-o++[c]=p%r
o%_=[]

Спробуйте в Інтернеті! Приклад використання: head.e "**_**_**_*_****_*"врожайність ((_*(_*(_*_)))*_). Усі символи, за винятком _інтерпретованих як оператори, _сам позначає ідентифікатор.


0

Пітон 3, 226 байт

from re import*
P=r'([*+]+)'+r'(\(.+?\)|_)\1'*2;R=lambda i,J=lambda i,o:i[:o]+sub(P,lambda o:'('+o[2]+o[1]+o[3]+')',i[o:],1),s=search:s(P,i)and R([J(i,o)for o in range(len(i))if s(P,J(i,o))or J(i,o)[0]+J(i,o)[-1]=='()'][0])or i

Визначає анонімну функцію з назвою R.

Спробуйте в Інтернеті!


Зауважте, що ви можете використовувати будь-які символи, крім _*+; це було саме те, що було використано в прикладі. Ви можете використовувати це для того, щоб поповнити свої реджекси (наприклад, використовуючи \dзамість них [*+]).
Esolanging Fruit
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.