Thực hiện ký hiệu Anyfix!


16

Trong ký hiệu tiền tố, toán tử xuất hiện trước các đối số, vì vậy bạn có thể tưởng tượng rằng toán tử gọi next()được gọi đệ quy. Trong ký hiệu infix, toán tử đi giữa các đối số, vì vậy bạn có thể tưởng tượng nó đơn giản là một cây phân tích cú pháp. Trong ký hiệu postfix, toán tử xuất hiện sau các đối số, vì vậy bạn chỉ có thể tưởng tượng nó là dựa trên ngăn xếp.

Trong ký hiệu anyfix, toán tử có thể đi bất cứ đâu * . Nếu một toán tử xuất hiện và không có đủ đối số, thì toán tử sẽ đợi cho đến khi có đủ đối số. Đối với thử thách này, bạn phải thực hiện một trình đánh giá anyfix rất cơ bản. (Lưu ý rằng anyfix là ngôn ngữ giải trí mà tôi đã từ bỏ mà bạn có thể chơi xung quanh tại đây hoặc xem tại đây )

Bạn sẽ cần hỗ trợ các lệnh sau:

(Arity 1)

  • bản sao
  • tiêu cực

(Arity 2)

  • thêm vào
  • phép nhân
  • bình đẳng: trả về 0hoặc 1.

Bạn có thể chọn sử dụng bất kỳ năm ký hiệu không phải khoảng trắng nào cho các lệnh này. Đối với mục đích trình diễn, tôi sẽ sử dụng "như là bản sao, ×nhân và +thêm.

Đối với chữ, bạn chỉ cần hỗ trợ các số nguyên không âm, nhưng trình thông dịch của bạn phải có thể chứa tất cả các số nguyên (trong phạm vi số nguyên (hợp lý) của ngôn ngữ của bạn).

Hãy xem một ví dụ : 10+5. Bộ lưu trữ nên hoạt động như một ngăn xếp, không phải là một hàng đợi. Vì vậy, đầu tiên, ngăn xếp bắt đầu tại []và danh sách toán tử xếp hàng bắt đầu tại []. Sau đó, nghĩa đen 10được đánh giá mà làm cho ngăn xếp [10]. Tiếp theo, toán tử +được ước tính, đòi hỏi hai đối số. Tuy nhiên, chỉ có một đối số trên ngăn xếp, vì vậy danh sách toán tử xếp hàng sẽ trở thành ['+']. Sau đó, nghĩa đen 5được đánh giá mà làm cho ngăn xếp [10, 5]. Tại thời điểm này, toán tử '+'có thể được đánh giá như vậy, tạo ngăn xếp [15]và hàng đợi [].

Kết quả cuối cùng sẽ được [15]cho + 10 5, 10 + 510 5 +.

Chúng ta hãy xem một ví dụ khó khăn hơn : 10+". Các ngăn xếp và hàng đợi bắt đầu như [][]. 10được đánh giá đầu tiên mà làm cho ngăn xếp [10]. Tiếp theo, +được đánh giá, không thay đổi ngăn xếp (vì không có đủ đối số) và tạo hàng đợi ['+']. Sau đó, "được đánh giá. Điều này có thể chạy ngay lập tức như vậy, làm cho ngăn xếp [10, 10]. +bây giờ có thể được đánh giá để ngăn xếp trở thành [20]và hàng đợi []. Kết quả cuối cùng là [20].

Điều gì về thứ tự của hoạt động?

Hãy xem xét ×+"10 10. Ngăn xếp và hàng đợi bắt đầu cả hai như []:

  • ×: Ngăn xếp không thay đổi và hàng đợi trở thành ['×'].
  • +: Ngăn xếp không thay đổi và hàng đợi trở thành ['×', '+'].
  • ": Ngăn xếp không thay đổi và hàng đợi trở thành ['×', '+', '"'].
  • 10: Ngăn xếp trở thành [10]. Mặc dù ×phải là toán tử đầu tiên được đánh giá kể từ khi nó xuất hiện đầu tiên, "có thể chạy ngay lập tức và không có toán tử nào trước khi có thể, vì vậy nó được đánh giá. Các ngăn xếp trở thành [10, 10]và hàng đợi ['×', '+']. ×bây giờ có thể được đánh giá, làm cho ngăn xếp [100]và hàng đợi ['+'].
  • 10: Ngăn xếp trở thành [100, 10], cho phép +được đánh giá. Các ngăn xếp trở thành [110]và hàng đợi [].

Kết quả cuối cùng là [110].

Các lệnh được sử dụng trong các trình diễn này phù hợp với ngôn ngữ anyfix; tuy nhiên, ví dụ cuối cùng sẽ không hoạt động do lỗi trong trình thông dịch của tôi. (Tuyên bố miễn trừ trách nhiệm: Nội dung gửi của bạn sẽ không được sử dụng trong trình thông dịch anyfix)

Thử thách

Chọn một bộ gồm 5 ký tự không phải chữ số không có khoảng trắng và tạo trình thông dịch anyfix theo các thông số kỹ thuật ở trên. Chương trình của bạn có thể xuất ra mảng số ít hoặc giá trị được chứa trong đó; đảm bảo rằng ngăn xếp các giá trị sẽ chỉ chứa một giá trị duy nhất khi kết thúc thực thi và hàng đợi của các toán tử sẽ trống khi kết thúc thực thi.

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

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

Đối với các trường hợp kiểm tra này, trùng lặp là ", âm là -, cộng là +, phép nhân là ×và đẳng thức là =.

Input -> Output
1+2×3 -> 9
1"+"+ -> 4
2"××" -> 16
3"×+" -> 18
3"+×" -> 36
123"= -> 1 ("= always gives 1)
1+2=3 -> 1
1"=2+ -> 3
1-2-+ -> -3
-1-2+ -> 3 (hehe, the `-1` becomes `+1` at the `-` rather than making the `2` a `-1`)
+×"10 10 -> 200 (after the 10 is duplicated (duplication is delayed), 10 + 10 is performed and then 20 * 10, giving 200)

Quy tắc

  • Áp dụng sơ hở tiêu chuẩn
  • Bạn có thể lấy trình thông dịch chính thức anyfix và đánh gôn nếu muốn. Hy vọng sẽ mất một cách khủng khiếp.

Đầu vào sẽ được cung cấp dưới dạng một chuỗi và đầu ra dưới dạng một mảng, một số nguyên duy nhất, ngoài biểu diễn chuỗi của một trong hai. Bạn có thể cho rằng đầu vào sẽ chỉ chứa khoảng trắng, chữ số và 5 ký tự bạn chọn.

* không thực sự


2
Đi bất cứ đâu * ™.
Jonathan Allan

Kết quả của toán tử đẳng là gì? 01?
Felix Palmen

1
@Jonathan ALLan xem ở trên; Tôi đã xóa lệnh rip
HyperNeutrino

1
@RickHitchcock Chắc chắn.
HyperNeutrino

1
Bạn có thể nên bao gồm ×+"10 10trong các trường hợp thử nghiệm hoặc bất kỳ ví dụ nào khác là 1) sử dụng khoảng trắng và 2) trì hoãn việc sử dụng toán tử trùng lặp (hai điều mà tôi đã bỏ lỡ hoàn toàn).
Arnauld

Câu trả lời:


5

JavaScript (ES6), 204 203 200 byte

Trả về một số nguyên.

e=>e.replace(/\d+|\S/g,v=>{for((1/v?s:v>','?u:b)[U='unshift'](v);!!u[0]/s[0]?s[U](u.pop()>'c'?s[0]:-S()):!!b[0]/s[1]?s[U](+eval(S(o=b.pop())+(o<'$'?'==':o)+S())):0;);},s=[],u=[],b=[],S=_=>s.shift())|s

Ký tự được sử dụng:

  • +: thêm vào
  • *: phép nhân
  • #: bình đẳng
  • d: bản sao
  • -: tiêu cực

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

Định dạng và nhận xét

e => e.replace(                     // given an expression e, for each value v matching
  /\d+|\S/g, v => {                 // a group of digits or any other non-whitespace char.
    for(                            //   this loop processes as many operators as possible
      (                             //   insert v at the beginning of the relevant stack:
        1 / v ? s : v > ',' ? u : b //     either value, unary operator or binary operator
      )[U = 'unshift'](v);          //     (s[], u[] or b[] respectively)
      !!u[0] / s[0] ?               //   if there's at least 1 value and 1 unary operator:
        s[U](                       //     unshift into s[]:
          u.pop() > 'c' ?           //       for the duplicate operator:
            s[0]                    //         a copy of the last value
          :                         //       else, for the negative operator:
            -S()                    //         the opposite of the last value
        ) :                         //     end of unshift()
      !!b[0] / s[1] ?               //   if there's at least 2 values and 1 binary operator:
        s[U](                       //     unshift into s[]:
          +eval(                    //       the result of the following expression:
            S(o = b.pop()) +        //         the last value, followed by the
            (o < '$' ? '==' : o) +  //         binary operator o with '#' replaced by '=='
            S()                     //         followed by the penultimate value
          )                         //       end of eval()
        ) : 0;                      //     end of unshift()
    );                              //   end of for()
  },                                // end of replace() callback
  s = [],                           // initialize the value stack s[]
  u = [],                           // initialize the unary operator stack u[]
  b = [],                           // initialize the binary operator stack b[]
  S = _ => s.shift()                // S = helper function to shift from s[]
) | s                               // return the final result

Đừng nghĩ rằng điều này làm việc cho -1+-2. Trả về 3 thay vì -3.
Rick Hitchcock

1
@RickHitchcock Hiểu biết của tôi là thứ 2 -phải được áp dụng -1ngay lập tức.
Arnauld

Tôi nghĩ rằng thứ 2 -sẽ đi với 2vì nó đến sau một nhà điều hành khác. Có lẽ @HyperNeutrino có thể làm rõ. Toán tử phủ định có thể mơ hồ trong một số tình huống.
Rick Hitchcock

3

JavaScript (ES6), 162 152 143 150 byte

(s,N=s.replace(/(-?\d+)-|-(-)/g,'- $1 ').match(/(- ?)*?\d+|R/g))=>+eval(`R=${N[0]>'9'?N[1]:N[0]},${s.match(/[+*=]/g).map((o,i)=>'R=R'+o+'='+N[i+1])}`)

Hơi vô dụng:

(s,
 N=s.replace(/(-?\d+)-|-(-)/g,'- $1 ').      //change postfix negatives to prefix,
                                             //and change "--" to "- - "
     match(/(- ?)*?\d+|R/g)                  //grab numbers and duplicates
)=>+eval(`R=${N[0] > '9' ?  N[1] : N[0]},    //handle a delayed duplicate
          ${s.match(/[+*=]/g).               //grab the operators
              map((o,i)=>'R=R'+o+'='+N[i+1]) //create a comma-separated list of assignments
           }
         `)

Giải trình

Tôi đang sử dụng *để nhân và Rnhân đôi. Các toán tử khác giống như trong câu hỏi.

N trở thành mảng của các số (bao gồm cả các bản sao).

Các replacexử lý trường hợp dấu âm đi sau số. Ví dụ, nó sẽ thay đổi 1-thành - 1-1-thành - -1.

Trong eval, s.matchtạo ra các toán tử nhị phân. Lưu ý rằng điều này sẽ luôn có một yếu tố ít hơn N.

Kết quả của hàm là evalánh xạ của các số và toán tử.

Đây là những gì evaled cho mỗi trường hợp thử nghiệm:

0+2*3        R=0,R=R+=2,R=R*=3        = 6 
1+2*3        R=1,R=R+=2,R=R*=3        = 9 
1R+R+        R=1,R=R+=R,R=R+=R        = 4 
2R**R        R=2,R=R*=R,R=R*=R        = 16 
3R*+R        R=3,R=R*=R,R=R+=R        = 18 
3R+*R        R=3,R=R+=R,R=R*=R        = 36 
123R=        R=123,R=R==R             = 1 
1+2=3        R=1,R=R+=2,R=R==3        = 1 
1R=2+        R=1,R=R==R,R=R+=2        = 3 
1-2-+        R=- 1,R=R+=- 2           = -3 
-1-2+        R=1,R=R+=2               = 3 
*+R10 10     R=10,R=R*=10,R=R+=10     = 110 
+*R10 10     R=10,R=R+=10,R=R*=10     = 200 
-1+--2       R=-1,R=R+=- -2           = 1 
-1+-2        R=-1,R=R+=-2             = -3 

Toán tử dấu phẩy trong biểu thức JavaScript trả về kết quả của biểu thức cuối cùng, do đó, maptự động trả về một biểu thức có thể sử dụng.

Các +dấu hiệu là cần thiết trước khi evalthay đổi trueđể 1falseđể 0.

Việc sử dụng Rnhư cả biến toán tử trùng lặp giúp đơn giản hóa rất nhiều mapbiểu thức con.

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


2
Tôi không nghĩ rằng các replacecông trình như dự định. Lợi nhuận này 3cho -1+--2và tôi nghĩ rằng 1sẽ là đúng (những 1thay đổi dấu ba lần trước khi có một cuộc tranh luận thứ hai cho +sẵn, kết quả -1 + 2).
Felix Palmen

Bắt tuyệt vời, @FelixPalmen. Bây giờ đã sửa.
Rick Hitchcock

2

JavaScript, 321 311 byte

_="f=a=>(a.replace(/\\d+|./g,mq!~(b='+*=\"- '.indexOf(a))|b>2j3j4j5&&o+aw1/y?(y*=-1wcz:1/y?oywcz:hz,rql.map(z=>m(lki,1)[0],i)),hq1/s[1]?sk0,2,+eval(`y${a=='='?a+a:a}s[1]`)):cz,cqlki,0,a),s=[],l=[],e='splice'),s)z(a,i)ys[0]w)^r``:q=z=>os.unshift(k[e](j?b-";for(i of"jkoqwyz")with(_.split(i))_=join(pop());eval(_)

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

Năm ký tự giống như trong câu hỏi, ngoại trừ *là để nhân.
Kịch bản được nén bằng RegPack . Kịch bản gốc được lưu trữ trong biến _sau khi đánh giá.


Đừng nghĩ rằng điều này làm việc cho -1+-2. Trả về 3 thay vì -3.
Rick Hitchcock

@RickHitchcock. Tại sao bạn tin rằng nó nên trở lại -3thay vì 3?

Tôi có thể hiểu nhầm các nhà điều hành tiêu cực. Nói chung -1 + -2-3, nhưng nó nên được phân tích cú pháp --1 + 2thay thế?
Rick Hitchcock

1
@RickHitchcock. Tôi khá chắc chắn kết quả là 3. Trước khi 2đến với stack, cái thứ hai -được đánh giá, và do đó chúng ta có 1 2 +cái thực sự 3. Ah, và có lẽ bạn cũng phải chỉnh sửa câu trả lời của mình.

Bạn có thể đúng. Bạn và Arnauld nhận được cùng một câu trả lời và tôi đã hỏi OP để làm rõ. Sẽ bỏ phiếu cho bạn một lần nữa nếu tôi có thể.
Rick Hitchcock

1

Haskell , 251 byte

(#([],[]))
(x:r)#(o,n)|x>'9'=r#h(o++[x],n)|[(a,t)]<-lex$x:r=t#h(o,read a:n)
_#(o,n:_)=n
h=e.e
e(o:s,n:m:r)|o>'N'=e(s,g[o]n m:r)
e(o:s,n:r)|o=='D'=e(s,n:n:r)|o=='N'=e(s,-n:r)
e(o:s,n)|(p,m)<-e(s,n)=(o:p,m)
e t=t
g"a"=(+)
g"m"=(*)
g"q"=(((0^).abs).).(-)

Hãy thử trực tuyến! Sử dụng các ký tự sau: ađể thêm, mnhân, qcho bằng, Dcho trùng lặp và Ncho phủ định. (Tôi muốn sử dụng echo đẳng thức, nhưng gặp vấn đề lexphân tích cú pháp 2e3dưới dạng số.) Ví dụ sử dụng: (#([],[])) "2a3 4m"sản lượng 20.


1

Mã máy 6502 (C64), 697 byte

00 C0 A2 00 86 29 86 26 86 27 86 28 86 4B 86 4C 86 CC 20 E4 FF F0 FB C9 0D F0
10 C9 20 30 F3 A6 27 9D B7 C2 20 D2 FF E6 27 D0 E7 C6 CC A9 20 20 1C EA A9 0D
20 D2 FF 20 95 C0 20 09 C1 20 95 C0 A6 26 E4 27 F0 4E BD B7 C2 E6 26 C9 20 F0
E8 C9 2D D0 09 A6 4C A9 01 9D B7 C3 D0 32 C9 22 D0 09 A6 4C A9 02 9D B7 C3 D0
25 C9 2B D0 09 A6 4C A9 81 9D B7 C3 D0 18 C9 2A D0 09 A6 4C A9 82 9D B7 C3 D0
0B C9 3D D0 0D A6 4C A9 83 9D B7 C3 E6 28 E6 4C D0 A3 4C 8A C2 A6 29 F0 6F A4
28 F0 6B CA F0 4B C6 28 A6 4B E6 4B BD B7 C3 F0 F5 30 14 AA CA D0 0B 20 7B C2
20 E1 C1 20 4D C2 D0 D9 20 5C C2 D0 D4 29 0F AA CA D0 0B 20 6D C2 20 08 C2 20
4D C2 D0 C3 CA D0 0B 20 6D C2 20 16 C2 20 4D C2 D0 B5 20 6D C2 20 F4 C1 20 4D
C2 D0 AA A4 4B B9 B7 C3 F0 02 10 AC C8 C4 4C F0 0F B9 B7 C3 F0 F6 30 F4 AA A9
00 99 B7 C3 F0 A6 60 A0 00 A6 26 E4 27 F0 15 BD B7 C2 C9 30 30 0E C9 3A 10 0A
E6 26 99 37 C4 C8 C0 05 D0 E5 C0 00 F0 08 A9 00 99 37 C4 20 39 C2 60 A2 FF E8
BD 37 C4 D0 FA A0 06 88 CA 30 0A BD 37 C4 29 0F 99 37 C4 10 F2 A9 00 99 37 C4
88 10 F8 A9 00 8D 3D C4 8D 3E C4 A2 10 A0 7B 18 B9 BD C3 90 02 09 10 4A 99 BD
C3 C8 10 F2 6E 3E C4 6E 3D C4 CA D0 01 60 A0 04 B9 38 C4 C9 08 30 05 E9 03 99
38 C4 88 10 F1 30 D2 A2 06 A9 00 9D 36 C4 CA D0 FA A2 10 A0 04 B9 38 C4 C9 05
30 05 69 02 99 38 C4 88 10 F1 A0 04 0E 3D C4 2E 3E C4 B9 38 C4 2A C9 10 29 0F
99 38 C4 88 10 F2 CA D0 D6 C0 05 F0 06 C8 B9 37 C4 F0 F6 09 30 9D 37 C4 E8 C8
C0 06 F0 05 B9 37 C4 90 F0 A9 00 9D 37 C4 60 A9 FF 45 FC 85 9F A9 FF 45 FB 85
9E E6 9E D0 02 E6 9F 60 A2 00 86 9F A5 FB C5 FD D0 07 A5 FC C5 FE D0 01 E8 86
9E 60 A5 FB 18 65 FD 85 9E A5 FC 65 FE 85 9F 60 A9 00 85 9E 85 9F A2 10 46 FC
66 FB 90 0D A5 FD 18 65 9E 85 9E A5 FE 65 9F 85 9F 06 FD 26 FE CA 10 E6 60 20
33 C1 A6 29 AD 3D C4 9D 3F C4 AD 3E C4 9D 3F C5 E6 29 60 A6 29 A5 9E 9D 3F C4
A5 9F 9D 3F C5 E6 29 60 A6 29 BD 3E C4 9D 3F C4 BD 3E C5 9D 3F C5 E6 29 60 C6
29 A6 29 BD 3F C4 85 FD BD 3F C5 85 FE C6 29 A6 29 BD 3F C4 85 FB BD 3F C5 85
FC 60 A6 29 BD 3E C5 10 13 20 7B C2 20 E1 C1 20 4D C2 A9 2D 20 D2 FF A6 29 BD
3E C5 8D 3E C4 BD 3E C4 8D 3D C4 20 8B C1 A9 37 A0 C4 4C 1E AB

Bản demo trực tuyến

Sử dụng sys49152 , sau đó nhập biểu thức anyfix và nhấn return.

  • gần như không kiểm tra lỗi, vì vậy mong đợi kết quả đầu ra hài hước trên các biểu thức không hợp lệ.
  • biểu tượng cho phép nhân là *, tất cả những thứ khác như được đề xuất.
  • độ dài đầu vào tối đa là 256 ký tự, không thể có hơn 127 toán tử xếp hàng.
  • Thói quen đầu vào không xử lý các ký tự điều khiển, vì vậy đừng gõ nhầm;)
  • số nguyên được ký 16 bit, tràn sẽ âm thầm bao quanh.
  • số byte là một chút lớn bởi vì CPU này thậm chí không biết phép nhân và C64 OS / ROM không cung cấp cho bạn bất kỳ số nguyên hoặc chuyển đổi nào sang / từ các chuỗi thập phân.

Đây là mã nguồn trình biên dịch mã trình biên dịch ca65 có thể đọc được .


1

VB.NET (.NET 4.5) 615 576 byte

-39 byte nhờ vào Felix Palmen bằng cách thay đổi \r\nthành\n

Yêu cầu Imports System.Collections.Generic(bao gồm trong số byte)

Dim s=New Stack(Of Long),q=New List(Of String),i=Nothing,t=0,c=0
Function A(n)
For Each c In n
If Long.TryParse(c,t)Then
i=i &"0"+t
Else
If c<>" "Then q.Add(c)
If i<>A Then s.Push(i)
i=A
End If
If i=A Then E
Next
If i<>A Then s.Push(i)
E
A=s
End Function
Sub E()
c=s.Count
If c=0Then Exit Sub
For Each op In q
If op="-"Or op="d"Or c>1Then
Select Case op
Case"*"
s.Push(s.Pop*s.Pop)
Case"+"
s.Push(s.Pop+s.Pop)
Case"="
s.Push(-(s.Pop=s.Pop))
Case"-"
s.Push(-s.Pop)
Case"d"
s.Push(s.Peek)
End Select
q.Remove(op)
E
Exit Sub
End If
Next
End Sub

Điểm vào là Hàm A, lấy một chuỗi làm đầu vào và trả về a Stack(Of Long).

Biểu tượng:

  • Thêm vào - +
  • Phép nhân - *
  • Bình đẳng - =
  • Phủ định - -
  • Sao chép - d

Tổng quat:

Hàm Alấy đầu vào và mã hóa nó. Nó sử dụng Long?tổng cộng để chạy các số nguyên có nhiều chữ số, điều này Nothingbiểu thị chúng ta hiện không đọc số nguyên.

Chương trình con Elấy chồng số nguyên và hàng đợi của các toán tử và đánh giá ký hiệu anyfix. Nó tự gọi đệ quy cho đến khi không còn hành động nào.

Tôi khai báo tất cả các thông số toàn cầu cùng một lúc để lưu byte trên cả khai báo và truyền tham số.

Giá trị trả về từ Ađược đặt bằng cách gán giá trị cho biến phù hợp A.

VB Truetương đương với -1, do đó thao tác phải phủ định kết quả để có giá trị chính xác.

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



btw, với Imports, tôi chỉ có một số byte 576- bạn có thể bị nhầm lẫn không?
Felix Palmen

@FelixPalmen Tôi đã tính \r\nthay vì \n, vì vậy đó là sự khác biệt.
Brian J

@FelixPalmen Đã thêm TIO, cảm ơn vì đã nhắc nhở tôi! :) (Ồ, tôi không nhận ra bạn đã tạo nó cho bài đăng này rồi)
Brian J
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.