Panfix ke infiks dipatenkan

16

Quylthulg adalah bahasa oleh Chris Pressey yang mencoba memecahkan masalah notasi infiks menggunakan apa yang disebut panfix :

seperti postfix, panfix tidak memerlukan penyebaran perangkat misterius seperti tanda kurung untuk mengesampingkan prioritas operator default. Pada saat yang sama, panfix memungkinkan istilah yang akan ditentukan dalam urutan dan cara yang sama seperti infix, notasi alami dan intuitif yang tidak diragukan lagi bagi mereka yang telah terbiasa dengannya.


Bagaimana Anda mendapatkan kenyamanan notasi infiks bersama dengan ambiguitas awalan atau postfix? Gunakan ketiganya, tentu saja!

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

Secara lebih formal, mari +menjadi operator, adan bmenjadi ekspresi. Kemudian (a+b)adalah ekspresi infiks yang valid (dalam tanda kurung), representasi panfix dari ekspresi itu adalah +a+b+, di mana penjajaran mewakili penggabungan.

Tujuan Anda adalah untuk mengambil string panfix dan mengonversinya menjadi infiks yang dipatenkan sepenuhnya:

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

Untuk mempermudah, kami akan melakukan perubahan berikut:

  • Operator hanya dapat terdiri dari dua karakter unik (Anda dapat memilih, tetapi di sini saya akan menggunakan *dan+ ).
  • Hanya ada satu literal, yang terdiri dari karakter lain yang berbeda (Anda dapat memilih salah satunya, tetapi di sini saya akan menggunakan _ ).
  • Input akan menjadi ekspresi panfix yang terbentuk dengan baik.

Untuk kompleksitas , kami akan melakukan perubahan berikut:

  • Operator dapat terdiri dari sejumlah karakter positif , bukan hanya satu.

Ini membuat tantangan lebih rumit karena Anda tidak dapat selalu menentukan bagaimana substring yang diberikan karakter operator dipartisi tanpa melihat sisa string.

Berikut ini adalah implementasi referensi untuk tantangan, milik @ user202729.

Uji Kasus

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

Saya menggunakan program ini untuk menghasilkan string infiks untuk tantangan ini (mengkonversi ke panfix itu sepele, tetapi membalikkan tidak).

Buah Esolanging
sumber
2
The inverse
Conor O'Brien
2
Terkait
HyperNeutrino
6
Kasus uji yang disarankan: **_**_**_*_****_*. Semua jawaban yang saya uji semuanya gagal.
Nitrodon
1
Bisakah saya memiliki ruang ekstra dalam output saya, misalnya (_ + _)?
Ton Hospel
2
@TonHospel Sure.
Buah Esolanging

Jawaban:

6

Prolog (SWI) , 194 163 byte

Menyimpan 31 byte kekalahan menggunakan tip ini dari 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-[].

Operator ^mengambil untuk argumen kirinya string yang berisi ekspresi panfix dan menetapkan argumen kanannya ke string yang berisi ekspresi infiks kurung yang sesuai. Ini digunakan xsebagai literal di tempat _.

Cobalah online!

Penjelasan

Karena Prolog adalah bahasa deklaratif, kita hanya perlu menjelaskan hubungan antara panfix dan ekspresi yang di-kurung.

Penjelasannya menggunakan versi yang sedikit tidak diubah ini:

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,[]).

Produksi utama kami adalah parenthesize, yang menggunakan ekspresi panfix Xsebagai string dan mengirimkan ekspresi infiks kurung yang sesuai Psebagai string. Ini digunakan string_charsuntuk mengubah string input menjadi daftar karakter dan kemudian meneruskannya ke expr.

exprmengambil daftar karakter L, mem-parsing ekspresi panfix pertama yang ditemukannya L, dan mengirimkan setara tanda kurung Xdan sisanya dari daftar karakter R. Ada dua jenis ekspresi yang mungkin:

  • Jika karakter pertama Ladalah x, maka ekspresi adalah xdan sisanya adalah segalanya setelahx .
  • Kalau tidak, parsing operator O(lihat di operbawah); parsing ekspresi Y; parse Olagi; uraikan ungkapan lain Z; dan uraikan Ountuk ketiga kalinya. Sisanya adalah segalanya setelah instance ketiga dari O. Ekspresi adalah hasil dari bergabung Y, Odan Z, dikelilingi oleh kurung, ke dalam string.

opermengambil daftar karakter, di mana karakter pertama berada Cdan sisanya berada T; itu mem-parsing operator (yaitu menjalankan satu atau lebih karakter operator) dan mengirimkan operator Odan sisa daftar karakter R. Untuk membentuk operator, karakter Charus berupa sesuatu selain x; juga

  • operator Pharus dapat diuraikan dari T, dengan sisanya R; dalam hal ini, Oadalah gabungan dari Cdan P; atau,
  • Oadalah karakter tunggal C; dalam hal ini, Radil T.

Contoh yang berhasil

Mari kita ambil input +*+x+x++*x+*sebagai contoh.

  • Kami ingin mem-parsing ekspresi dari +*+x+x++*x+*. Ini tidak dimulai dengan x, jadi kami mengurai operator dari awal.
  • oper akan mem-parsing operator sebesar mungkin, jadi kami mencoba +*+ .
    • Selanjutnya kita parsing ekspresi dari x+x++*x+*. Ini pastix .
    • Sekarang kami mencoba menguraikan operator yang sama +*+,, dari +x++*x+*. Namun, ini gagal .
  • Jadi kami mundur dan mencoba mem-parsing operator +* sebagai gantinya.
    • Kami mem-parsing ekspresi dari +x+x++*x+*. Ini tidak dimulai dengan x, jadi kita perlu mengurai operator.
    • Satu-satunya kemungkinan adalah +.
    • Sekarang parsing subekspresi dari x+x++*x+*. Ini pasti x.
    • Sekarang parse +lagi dari +x++*x+*.
    • Sekarang parsing subekspresi lain dari x++*x+*. Ini pasti x.
    • Akhirnya, uraikan +lagi dari ++*x+*.
    • Ekspresi telah berhasil diuraikan. Kami mengembalikan string (x+x).
  • Kembali pada level rekursi sebelumnya, kami mem-parsing operator +*lagi +*x+*.
  • Sekarang parsing subekspresi lain dari x+*. Ini pasti x.
  • Akhirnya, uraikan +*lagi dari +*.
  • Ekspresi telah berhasil diuraikan. Kami mengembalikan string ((x+x)+*x).

Karena tidak ada lagi karakter yang tersisa, kami telah berhasil menerjemahkan ekspresi.

DLosc
sumber
4

Perl, 78 60 58 57 50 byte

Termasuk +1untukp

Penggunaan 1untuk +dan 2untuk *(atau sebenarnya digit apa pun bekerja untuk operator apa pun)

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

Untuk pengujian yang mudah dibandingkan contoh yang diberikan, Anda dapat menggunakan ini yang melakukan terjemahan dan penghapusan ruang untuk Anda:

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

Bersih , 200 192 189 byte

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))]

Cobalah online!

Menentukan fungsi f, mengambil String, dan mengembalikan singleton [String]dengan hasil di dalamnya.

Beberapa hal rapi:

  • Tidak menggunakan regex
  • Bekerja dengan karakter apa pun untuk operator kecuali_
Suram
sumber
3

Retina 0.8.2 , 138 byte

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

Cobalah online! Tautan termasuk kasus uji lebih cepat. Penjelasan: Mesin regex menggunakan backtracking untuk membagi string menjadi token yang kemudian didorong atau muncul dari ikelompok balancing. Selalu ada setidaknya satu operator yang didorong di awal sebelum variabel pertama. Setelah variabel, setidaknya satu operator muncul, pada titik mana operator didorong dijalankan atau variabel lain legal. Operator didorong ke grup dalam rangkap sehingga mereka dapat muncul dengan benar. Contoh:

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 *

Sayangnya ini tidak membantu kami menangkap hasilnya untuk mengurungnya, sehingga operator luar dicocokkan secara manual. Tanda kurung ditambahkan di luar-dalam, jadi tahap pertama membungkus seluruh ekspresi dalam tanda kurung dan tahap terakhir menghapusnya sekarang karena mereka telah menyebar ke variabel.

Neil
sumber
1
Ini juga gagal untuk **_**_**_*_****_*.
user202729
@ user202729 Bekerja sekarang?
Neil
@ Neil Ini bekerja sekarang, ya.
Kamis
1

Haskell , 167 166 byte

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%_=[]

Cobalah online! Contoh penggunaan: head.e "**_**_**_*_****_*"hasil ((_*(_*(_*_)))*_). Semua karakter kecuali _ditafsirkan sebagai operator, _itu sendiri menunjukkan pengenal.

Laikoni
sumber
0

Python 3, 226 byte

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

Menentukan fungsi anonim bernama R.

Cobalah secara Online!

R. Kap
sumber
Perhatikan bahwa Anda dapat menggunakan karakter apa pun selain _*+; itu hanya apa yang digunakan dalam contoh. Anda mungkin dapat menggunakan ini untuk mengatur regex Anda (misalnya dengan menggunakan \dalih-alih [*+]).
Buah Esolanging