Panfix để dấu ngoặc đơn


16

Quylthulg là một ngôn ngữ của Chris Pressey, cố gắng giải quyết vấn đề ký hiệu trung gian bằng cách sử dụng cái mà nó gọi là panfix :

Giống như postfix, panfix không yêu cầu triển khai các yếu tố phức tạp như dấu ngoặc đơn để ghi đè lên một ưu tiên toán tử mặc định. Đồng thời, panfix cho phép các thuật ngữ được chỉ định theo cùng thứ tự và cách thức như infix, một ký hiệu tự nhiên và trực quan không thể nghi ngờ đối với những người đã quen với nó.


Làm thế nào để bạn có được sự thuận tiện của ký hiệu infix cùng với sự không rõ ràng của tiền tố hoặc hậu tố? Sử dụng cả ba, tất nhiên!

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

Chính thức hơn, hãy +là một toán tử, ablà biểu thức. Sau đó (a+b)là một biểu thức infix hợp lệ (được ngoặc đơn), biểu diễn panfix của biểu thức đó là +a+b+, trong đó juxtap vị trí đại diện cho nối.

Mục tiêu của bạn là lấy một chuỗi panfix và chuyển đổi nó thành infix được ngoặc đơn đầy đủ:

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

Để đơn giản, chúng tôi sẽ thực hiện các thay đổi sau:

  • Toán tử chỉ có thể bao gồm hai ký tự duy nhất (bạn có thể chọn bất kỳ ký tự nào, nhưng ở đây tôi sẽ sử dụng *+).
  • Chỉ có một nghĩa đen, bao gồm một ký tự riêng biệt khác (bạn có thể chọn bất kỳ, nhưng ở đây tôi sẽ sử dụng _ ).
  • Đầu vào sẽ là một biểu thức panfix được hình thành tốt.

Để phức tạp , chúng tôi sẽ thực hiện thay đổi sau:

  • Các nhà khai thác có thể bao gồm bất kỳ số lượng ký tự tích cực , không chỉ một.

Điều này làm cho thử thách trở nên khó khăn hơn vì bạn không nhất thiết phải xác định cách một chuỗi các ký tự toán tử đã cho được phân vùng mà không cần nhìn vào phần còn lại của chuỗi.

Dưới đây là một triển khai tham chiếu cho thử thách, lịch sự của @ user202729.

Các trường hợp thử nghiệm

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

Tôi đã sử dụng chương trình này để tạo chuỗi infix cho thử thách này (chuyển đổi sang panfix là không đáng kể, nhưng đảo ngược thì không).




6
Trường hợp thử nghiệm đề xuất : **_**_**_*_****_*. Các câu trả lời tôi đã kiểm tra đều thất bại trong câu trả lời này.
Nitrodon

1
Tôi có thể có thêm không gian trong đầu ra của mình không, ví dụ (_ + _)?
TonMedel 5/2/18

2
@TonHeach Chắc chắn.
Esolanging Fruit 5/2/18

Câu trả lời:


6

Prolog (SWI) , 194 163 byte

Đã lưu một con số khổng lồ 31 byte bằng mẹo này từ 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-[].

Toán tử ^lấy đối số bên trái của nó một chuỗi chứa biểu thức panfix và đặt đối số bên phải của nó thành một chuỗi chứa biểu thức dấu ngoặc đơn tương ứng. Nó sử dụng xnhư nghĩa đen thay cho _.

Hãy thử trực tuyến!

Giải trình

Vì Prolog là ngôn ngữ khai báo, chúng ta chỉ cần mô tả mối quan hệ giữa một từ khóa và biểu thức được ngoặc đơn.

Giải thích sử dụng phiên bản hơi vô căn cứ này:

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

Sản phẩm chính của chúng tôi là parenthesize, lấy một biểu thức panfix Xdưới dạng một chuỗi và gửi ra biểu thức infix ngoặc đơn tương ứng Pdưới dạng một chuỗi. Nó sử dụng string_charsđể chuyển đổi chuỗi đầu vào thành một danh sách các ký tự và sau đó chỉ cần chuyển nó vào expr.

exprnhận một danh sách các ký tự L, phân tích biểu thức panfix đầu tiên mà nó tìm thấy Lvà gửi ra tương đương dấu ngoặc đơn Xvà phần còn lại của danh sách các ký tự R. Có hai loại biểu thức có thể:

  • Nếu ký tự đầu tiên Lx, thì biểu thức là xvà phần còn lại là mọi thứ sau x.
  • Mặt khác, phân tích một toán tử O(xem operbên dưới); phân tích một biểu thức Y; phân tích Olại; phân tích một biểu thức khác Z; và phân tích Olần thứ ba. Phần còn lại là tất cả mọi thứ sau phiên bản thứ ba của O. Khái niệm là kết quả của việc gia nhập Y, OZ, được bao quanh bởi dấu ngoặc đơn, thành một chuỗi.

operđưa vào một danh sách các ký tự, trong đó ký tự đầu tiên Cvà phần còn lại là T; nó phân tích một toán tử (tức là chạy một hoặc nhiều ký tự toán tử) và gửi toán tử Ovà phần còn lại của danh sách các ký tự R. Để tạo thành một toán tử, nhân vật Cphải là một cái gì đó khác hơn x; cũng có thể

  • một toán tử Pphải được phân tích cú pháp từ T, với phần còn lại R; trong trường hợp này, Olà sự kết hợp của CP; hoặc là,
  • Olà nhân vật duy nhất C; trong trường hợp này, Rchỉ là T.

Một ví dụ làm việc

Hãy lấy đầu vào +*+x+x++*x+*làm ví dụ.

  • Chúng tôi muốn phân tích một biểu thức từ +*+x+x++*x+*. Điều này không bắt đầu với x, vì vậy chúng tôi phân tích một toán tử ngay từ đầu.
  • opersẽ phân tích cú pháp càng lớn của một toán tử càng tốt, vì vậy chúng tôi thử +*+.
    • Tiếp theo chúng tôi phân tích một biểu thức từ x+x++*x+*. Điều này phải được x.
    • Bây giờ chúng tôi cố gắng phân tích cùng một toán tử +*+, từ +x++*x+*. Tuy nhiên, điều này thất bại .
  • Vì vậy, chúng tôi quay lại và thử phân tích cú pháp toán tử +*thay thế.
    • Chúng tôi phân tích một biểu thức từ +x+x++*x+*. Điều này không bắt đầu với x, vì vậy chúng ta cần phân tích một toán tử.
    • Khả năng duy nhất là +.
    • Bây giờ phân tích một subexpression từ x+x++*x+*. Điều này phải được x.
    • Bây giờ phân tích +lại từ +x++*x+*.
    • Bây giờ phân tích một subexpression khác từ x++*x+*. Điều này phải được x.
    • Cuối cùng, phân tích +lại từ ++*x+*.
    • Biểu thức đã được phân tích thành công. Chúng tôi trả lại chuỗi (x+x).
  • Quay lại mức đệ quy trước đó, chúng tôi phân tích lại toán tử +*từ +*x+*.
  • Bây giờ phân tích một subexpression khác từ x+*. Điều này phải được x.
  • Cuối cùng, phân tích +*lại từ +*.
  • Biểu thức đã được phân tích thành công. Chúng tôi trả lại chuỗi ((x+x)+*x).

Vì không còn ký tự nào nữa, chúng tôi đã dịch thành công biểu thức.


4

Perl, 78 60 58 57 50 byte

Bao gồm +1chop

Sử dụng 1cho +2cho *(hoặc trên thực tế bất kỳ chữ số nào hoạt động cho bất kỳ toán tử nào)

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

Để kiểm tra thuận tiện so với các ví dụ đã cho, bạn có thể sử dụng bản dịch này để loại bỏ bản dịch và không gian cho bạn:

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

3

Sạch , 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))]

Hãy thử trực tuyến!

Xác định hàm f, lấy Stringvà trả về một singleton [String]với kết quả bên trong.

Một số thứ gọn gàng:

  • Không sử dụng regex
  • Hoạt động với bất kỳ ký tự nào cho các toán tử ngoại trừ_

3

Võng mạc 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))
\(_\)
_

Hãy thử trực tuyến! Liên kết bao gồm các trường hợp thử nghiệm nhanh hơn. Giải thích: Công cụ regex sử dụng quay lui để tách chuỗi thành các mã thông báo sau đó được đẩy lên hoặc bật ra khỏi inhóm cân bằng. Có một hoạt động luôn luôn có ít nhất một toán tử được đẩy khi bắt đầu trước biến đầu tiên. Sau một biến, ít nhất một toán tử được bật lên, tại đó một toán tử được đẩy chạy hoặc một biến khác là hợp pháp. Các toán tử được đẩy vào nhóm theo bản sao để chúng có thể được bật chính xác. Thí dụ:

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 *

Thật không may, điều này không giúp chúng tôi nắm bắt các kết quả để đặt dấu ngoặc cho chúng, do đó toán tử bên ngoài được khớp thủ công. Các dấu ngoặc được thêm vào bên ngoài, vì vậy giai đoạn đầu tiên bao bọc toàn bộ biểu thức trong ngoặc và giai đoạn cuối sẽ loại bỏ chúng ngay bây giờ khi chúng được truyền xuống các biến.


1
Điều này cũng thất bại cho **_**_**_*_****_*.
dùng202729

@ user202729 Làm việc bây giờ?
Neil

@Neil Nó đang hoạt động, vâng.
Οurous

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

Hãy thử trực tuyến! Ví dụ sử dụng: head.e "**_**_**_*_****_*"sản lượng ((_*(_*(_*_)))*_). Tất cả các ký tự ngoại trừ _được hiểu là toán tử, _chính nó biểu thị một định danh.


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

Xác định một hàm ẩn danh có tên R .

Hãy thử trực tuyến!


Lưu ý rằng bạn có thể sử dụng bất kỳ ký tự nào khác ngoài _*+; đó chỉ là những gì đã được sử dụng trong ví dụ. Bạn có thể có thể sử dụng điều này để đánh golf regexes của mình (ví dụ: bằng cách sử dụng \dthay vì [*+]).
Trái cây Esolanging
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.