Chuyển đổi một biểu thức thành ký hiệu Panfix


19

Tôi đã duyệt esolang và tình cờ thấy ngôn ngữ này: https://github.com/catseye/Quylthulg .

Một điều thú vị về ngôn ngữ này là nó không sử dụng tiền tố, hậu tố hoặc infix, nó sử dụng cả ba từ này , gọi đó là ký hiệu "panfix".

Đây là một ví dụ. Để thể hiện infix bình thường 1+2trong panfix, nó trở thành : +1+2+. Lưu ý cách toán tử là cả trước, giữa và sau toán hạng. Một ví dụ khác là (1+2)*3. Điều này trở thành *+1+2+*3*. Lưu ý một lần nữa làm thế nào *là ở cả ba nơi đối với toán hạng +1+2+3.

Các thách thức

Như bạn có thể đoán, nhiệm vụ của bạn trong thử thách này là chuyển đổi một biểu thức từ infix sang panfix.

Một vài điều rõ ràng:

  • Bạn chỉ phải đối phó với bốn thao tác cơ bản: +-*/
  • Bạn sẽ không phải đối phó với các phiên bản đơn nhất của những phiên bản đó, chỉ là nhị phân
  • Bạn phải đối phó với dấu ngoặc đơn
  • Giả sử các quy tắc ưu tiên bình thường của */sau đó +-và tính kết hợp trái cho tất cả chúng.
  • Các số sẽ là số nguyên không âm
  • Bạn có thể có một khoảng trắng ở cả đầu vào và đầu ra

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

1+2  ->  +1+2+
1+2+3  ->  ++1+2++3+
(1+2)*3  ->  *+1+2+*3*
10/2*5  ->  */10/2/*5*
(5+3)*((9+18)/4-1)  ->  *+5+3+*-/+9+18+/4/-1-*

Đây là , vì vậy mã ngắn nhất tính bằng byte sẽ thắng!

Câu trả lời:


3

JavaScript (ES6), 160 byte

f=(s,t=s.replace(/[*-/]/g,"'$&'"),u=t.replace(/^(.*?)([*-9]+)'([*/])'([*-9]+)|([*-9]+)'([+-])'([*-9]+)|\(([*-9]+)\)/,"$1$3$2$3$4$3$6$5$6$7$6$8"))=>t==u?t:f(s,u)

Hoạt động bằng cách trích dẫn tất cả các toán tử (cung cấp cho chúng mã ký tự trước đó *), sau đó tìm kiếm có sẵn '*'hoặc các '/'hoạt động, '+'hoặc các '-'hoạt động hoặc ()s, và thay thế đầu tiên bằng ký hiệu panfix của nó. Thí dụ:

(5+3)*((9+18)/4-1)
(5'+'3)'*'((9'+'18)'/'4'-'1)
(+5+3+)'*'((9'+'18)'/'4'-'1)
+5+3+'*'((9'+'18)'/'4'-'1)
+5+3+'*'((+9+18+)'/'4'-'1)
+5+3+'*'(+9+18+'/'4'-'1)
+5+3+'*'(/+9+18+/4/'-'1)
+5+3+'*'(-/+9+18+/4/-1-)
+5+3+'*'-/+9+18+/4/-1-
*+5+3+*-/+9+18+/4/-1-*

3

JavaScript (ES6), 285 282 281 267 251 243 241 238 234 232 232 byte

~ 15 byte nhờ Neil .

f=(I,E=I.match(/\d+|./g),i=0)=>(J=T=>T.map?T.map(J).join``:T)((R=(H,l=(P=_=>(t=E[i++])<")"?R(0):t)(),C,F)=>{for(;(C=P())>")"&&(q=C>"*"&&C<"/")*H-1;)F=q+H?l=[C,l,C,P(),C]:F?l[3]=[C,l[3],C,R(1),C]:l=R(1,l,i--)
i-=C>")"
return l})(0))

Trong JavaScript, điều này khó hơn một chút so với Mathicala. Điều này về cơ bản là quá chuyên môn và chơi gôn trình phân tích cú pháp ưu tiên vận hành .

Nguyên nhân ngăn xếp tràn vào đầu vào không hợp lệ.

Bản giới thiệu

Bị đánh cắp

convert = input => {
  tokens = input.match(/\d+|./g);
  i = 0;
  parse_token = () => (token = tokens[i++]) == "(" ? parse_tree(false) : token;
  parse_tree = (mul_div_mode, left = parse_token()) => {
    while ((oper = parse_token()) != ")" && !((is_plus_minus = oper == "+" || oper == "-") && mul_div_mode)) {
      if (is_plus_minus || mul_div_mode)
        left = [oper, left, oper, parse_token(), oper];
      else if (non_first)
        left[3] = [oper, left[3], oper, parse_tree(true), oper];
      else
        left = parse_tree(true, left, i--);
      non_first = true;
    }
    if (oper != ")")
      i--;
    return left;
  };
  format_tree = tree => tree.map ? tree.map(format_tree).join("") : tree;
  return format_tree(parse_tree(false));
}

S.split``nên [...S], mặc dù nó thực sự có thể giúp phù hợp với /\d+|./gmặt trận và thay vào đó làm việc trên đó.
Neil

@Neil Cảm ơn. Tôi sẽ xem xét điều đó.
PurkkaKoodari

2

Toán học, 203 195 byte

Điều này có thể ít hơn hiệu quả, nhưng dường như thực hiện công việc.

Function[f,ReleaseHold[(Inactivate@f/._[Plus][a_,b_/;b<0]:>a~"-"~-b//Activate@*Hold)//.a_/b_:>a~"/"~b/.{a_Integer:>ToString@a,Plus:>"+",Times:>"*"}]//.a_String~b_~c_String:>b<>a<>b<>c<>b,HoldAll]

Đây là một hàm ẩn danh nhận một biểu thức thực tế và trả về một chuỗi có ký hiệu panfix. Mathicala sắp xếp thứ tự ưu tiên của các toán tử tại thời điểm phân tích cú pháp, thay vì thời gian đánh giá, do đó, việc lồng phải được tự động chính xác. Ít nhất là các trường hợp thử nghiệm làm việc như mong đợi.

Giải thích: Thật dễ dàng để diễn giải toàn bộ biểu thức dưới dạng cây, như vậy:

cây

Ở giai đoạn này, các toán tử (mỗi nút không phải là một lá) không còn là toán tử nữa, chúng thực sự đã được chuyển đổi thành các chuỗi như "+". Các số nguyên cũng được đúc thành chuỗi. Sau đó, một quy tắc thay thế lặp đi lặp lại sẽ chuyển đổi mọi nút có chính xác hai lá thành panfixparent-leaf1-parent-leaf2-parent . Sau một số lần lặp, cây giảm xuống một chuỗi.

Mất mát chính trong số byte là các phiên dịch Mathicala

5 - 4 -> 5 + (-4)
9 / 3 -> 9 * (3^(-1))

Và điều này cũng xảy ra tại thời điểm phân tích cú pháp.

Chơi golf xuống một chút, vì mô hình a_/b_cũng được hiểu là a_ * (b_)^(-1). Ngoài ra một số tối ưu hóa nhỏ ở nơi khác.


1

Prolog, 87 byte

x(T)-->{T=..[O,A,B]}->[O],x(A),[O],x(B),[O];[T].
p:-read(T),x(T,L,[]),maplist(write,L).

Đây là một chức năng (chủ yếu là do viết một chương trình đầy đủ có mức độ sôi nổi trong Prolog; thông thường, ngay cả khi bạn biên dịch chương trình, nó sẽ tạo ra REPL khi chạy), được gọi p. Nó nhận đầu vào từ stdin và đầu ra trên thiết bị xuất chuẩn. Lưu ý rằng bạn cần nối thêm một khoảng thời gian vào đầu vào, đó là hậu quả đáng tiếc của cách thức hoạt động của thói quen nhập liệu của Prolog (chúng sử dụng các khoảng thời gian trong đầu vào giống như cách các ngôn ngữ khác sử dụng dòng mới); điều đó có thể hoặc không thể loại bỏ câu trả lời.

Giải trình

Toán tử số học, trong Prolog, thường được hiểu là các hàm tạo tuple . Tuy nhiên, họ tuân theo các quy tắc ưu tiên giống như các toán tử số học thực tế mà họ dựa trên; bạn có thể tạo các bộ dữ liệu với ký hiệu infix +-liên kết ít chặt chẽ hơn*/, với quyền ưu tiên được chuyển từ trái sang phải trong một nhóm. Đây chính xác là những gì câu hỏi yêu cầu; do đó, chúng ta có thể đọc toàn bộ bộ dữ liệu lồng nhau từ đầu vào và nó đã có cấu trúc đúng. Đó là những gì p.

Tiếp theo, chúng ta cần chuyển đổi nó thành ký hiệu panfix. xchuyển đổi đầu vào thành một danh sách panfixed của nhà thầu và số nguyên, và có thể được đọc như một câu tiếng Anh gần như trực tiếp: " xcủa Tlà: nếu Tlà một tuple với nhà xây dựng Ovà lập luận A, Bthì O, xcủa A, O, xcủa B, O, khác T". Cuối cùng, chúng ta chỉ cần in danh sách mà không có bất kỳ dấu phân cách nào (nghĩa là sử dụng maplistđể gọiwrite trên từng thành phần của danh sách).

Tôi đã sử dụng SWI-Prolog để kiểm tra điều này, vì phiên bản GNU Prolog của tôi chưa có maplist(dường như nó đã được thêm vào phiên bản mới hơn), nhưng nhìn chung nó sẽ khá dễ di chuyển giữa các lần triển khai Prolog.

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.