Flak thứ ba!


19

Thử thách này đã được đăng trong khuôn khổ thử thách LotM tháng 4 năm 2018


Brain-Flak là một ngôn ngữ turing-tarpit đã đạt được khá nhiều danh tiếng ở đây trên PPCG. Bộ nhớ của ngôn ngữ được cấu thành bởi hai ngăn xếp, nhưng ngăn xếp thứ ba "ẩn" được phát hiện bởi Wh e tại Wizard , dẫn đến một số cách suy nghĩ mới thú vị về các chương trình Brain-Flak.

Vì vậy, những gì về việc cung cấp cho ngăn xếp thứ ba nghèo ẩn đó khả năng hiển thị nhiều hơn? Hãy tạo một ngôn ngữ trong đó ngăn xếp thứ ba có sự công nhận mà nó xứng đáng! Ở đây tôi giới thiệu bạn Thứ ba-Flak .

Ngôn ngữ

Trong Third-Flak chỉ có một ngăn xếp, được gọi là ngăn xếp thứ ba. Các nhà khai thác làm việc trên stack thứ ba trong cùng một cách mà họ làm trong Brain-Flak, nhưng ở đây không có [], {}, <>nilads và không có {...}đơn nguyên (vì vậy các nhân vật chỉ có thể chấp nhận trong một chương trình thứ ba Flak là ()[]<>). Dưới đây là những gì mỗi toán tử thực hiện (các ví dụ sẽ được đưa ra đại diện cho ngăn xếp thứ ba với một danh sách trong đó phần tử cuối cùng là đỉnh của ngăn xếp):

  • ()là toán tử hai ký tự duy nhất trong Thứ ba-Flak. Nó tăng đỉnh của ngăn xếp thứ ba lên 1. Ví dụ: [1,2,3][1,2,4]

  • (, [, <: Tất cả các dấu ngoặc đơn mở mà không được bao phủ bởi các trường hợp trước đẩy một 0để ngăn xếp thứ ba. Ví dụ: [1,2,3][1,2,3,0]

  • )bật hai phần tử từ ngăn xếp thứ ba và đẩy lùi tổng của chúng. Ví dụ: [1,2,3][1,5]

  • ]bật hai phần tử từ ngăn thứ ba và đẩy lùi kết quả trừ phần thứ nhất từ ​​phần thứ hai. Ví dụ: [1,2,3][1,-1]

  • >bật một phần tử từ ngăn xếp thứ ba. Ví dụ [1,2,3][1,2]

Và đây là các quy tắc khác của ngôn ngữ:

  • Khi bắt đầu thực hiện, ngăn xếp thứ ba chỉ chứa một 0 duy nhất.

  • Không được để trống []hoặc <>bên trong một chương trình (dù sao họ cũng sẽ bị bỏ qua nếu theo ngữ nghĩa của Thứ ba, nhưng chúng thực sự có một ý nghĩa khác trong Brain-Flak không thể tái tạo ở đây).

  • Dấu ngoặc đơn luôn cần được cân bằng, ngoại trừ thực tế là dấu ngoặc đơn đóng ở cuối chương trình có thể bị thiếu. Ví dụ, [()<(()là một chương trình Thứ ba hợp lệ (và ngăn xếp thứ ba ở cuối chương trình sẽ là [1,0,1]).

  • Một chương trình chỉ có thể chứa sáu ký tự được phép ()[]<>. Các chương trình được đảm bảo không trống.

Lưu ý: được ngụ ý bởi các quy tắc trước đây mà bạn sẽ không phải đối phó với các tình huống mà bạn cần phải bật từ một ngăn xếp trống.

Các thách thức

Đơn giản, viết một thông dịch viên cho Thứ ba-Flak. Chương trình của bạn phải nhận đầu vào là chương trình Thứ ba và trả về làm đầu ra trạng thái của ngăn xếp thứ ba ở cuối chương trình.

Định dạng đầu ra của bạn linh hoạt miễn là có thể đọc rõ ràng từ trạng thái của ngăn xếp thứ ba và cùng một số luôn được mã hóa theo cùng một cách (Đây chỉ là một cách để nói rằng bất kỳ định dạng đầu ra nào không phải là một cách trắng trợn để cố gắng gian lận là tốt).

Lựa chọn đầu ra của bạn có thể hạn chế phạm vi số bạn có thể quản lý miễn là điều này không tầm thường hóa thách thức (vì đây sẽ là lỗ hổng mặc định ).

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

Đối với mỗi trường hợp kiểm tra, dòng đầu tiên là đầu vào và dòng thứ hai, ngăn xếp đầu ra được biểu diễn dưới dạng một danh sách các số được phân tách bằng dấu cách trong đó đỉnh của ngăn xếp là phần tử cuối cùng.

[()<(()
0 1 0 1

[((((()()()()()))
0 0 0 5

((([()][()][()])))
-3

[<<(((()()()())(((((
0 0 0 0 0 4 0 0 0 0 0

[()]<(([()])><[()]
-1 0 -1

(())(()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(()()())(())(()()()()())(())(())(())(())(()()()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(()()())(())(()()()()())(())(())(())(())(())(())(()())(())(())(())(()())(()()()())(())(()()()()())(()())(()())(()())(()()())(())(()())(())(()()()()())(()())(()()()()())(())(())(())(())(())(()())(())(())(())(()()()()())(())(())(()()()()())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(()())(()())(()())(()())(())(()()()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(()()())(())(())(()()())(()())(())(()()()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(())(())(()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(()()())(())(()()())(())(())(())(()())(()()())(()())(())(()()()()())(()())(())(()()())(())(()()()()())(())(())(())(()()())(())(())(())(()())(())(()())(()()()())(())(())(()()()()())(()())(()())(())(()()())(())(())(())(())(()()())(()())(())(())(()()()()())(())(())(()()()()())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(())(()()()()())(()())(())(()()())(())(()()()()())(()()()()())(())(()()())(())(())(()())(())(()()()()())(())(()()()()())(())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(())(()()()()())(()())(())(()()())(())(())(()())(())(()()()()())(()())(()()()()())(())(()()())(())(())(()()()()())(())(()()()()())(())(())(())(()())(())(()()()()())(())(())(()())(())(()())(())(()())(()())(()())(()())(())(()()()()())(()())(())(()()()()())(())(()()())(())(())(()())(())(()()()()())(()())(()()()()())(())(()()())(())(())(())(()())(()()()())(())(())(()())(())(()()()()())(())(())(()()()()())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(()())(()())(())(()()())(())(())(()())(())(()()()()())(()())(()()()()())(()()())(())(())(()())(())(())(()()()()())(()()()())(()())(()())(()()())(())(()())(())(()()()()())(()())(()()()()())(())(())(())(()()()())(()()()())(()()
718 2

Là ngăn xếp được khởi tạo với 0? Nếu không thì [()]phá vỡ quy tắc mà chúng ta không cần phải lo lắng về việc bật ra từ một ngăn xếp trống
Jo King

1
@JoKing Yep: "Khi bắt đầu thực thi, ngăn xếp thứ ba chỉ chứa một 0". Có lẽ tôi nên làm nổi bật phần đó một chút, tôi sợ nó sẽ quá dễ bỏ lỡ.
Leo

Rất tiếc, tôi không biết làm thế nào tôi đã bỏ lỡ điều đó
Jo King

7
Vượt qua e vẫn là e.
Thuật sĩ lúa mì

2
Nếu bất cứ ai không thể nhìn thấy điều đó, gạch bỏ eở đây .
dùng202729

Câu trả lời:


21

Brain-Flak , 276 byte

{({}<>)<>}<>{(((()()()()()){})((({}){})())(({})({}{}([{}])(<>))))((()()(){[()]<{}>}{}){()<{{}}>}{}<<>({}({})())>{()(<{}>)}{}<>)<>}<>{(([{}]()<>)){{}({}())((){[()](<({}())((){[()](<({}())((){[()](<{}([{}]{})>)}{}){(<{}{}>)}{}>)}{}){(<{}({}{})>)}{}>)}{}){(<{}{}({}())>)}}{}<>}<>

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

Bạn phải biết điều này đã đến.


4

Võng mạc 0.8.2 , 64 48 46 byte

\(\)
_
[([<]
¶
+1`¶(.*)\)|(.*)¶\2]|¶.*>
$1
%`_

Hãy thử trực tuyến! Xuất ra ngăn xếp từ dưới lên trên. Chỉ hoạt động với số nguyên không âm và trường hợp thử nghiệm cuối cùng quá chậm, vì vậy liên kết chỉ bao gồm ba trường hợp thử nghiệm. Giải thích: Ngăn xếp ngầm định trước chương trình, do đó, nó bắt đầu dưới dạng chuỗi rỗng, đại diện cho một số không. Các ()nilad được biến thành một _được sử dụng để đếm trong unary, trong khi dấu ngoặc mở khác được biến thành dòng mới mà đẩy một số không vào ngăn xếp như họ đang gặp phải. Các dấu ngoặc đóng sau đó được xử lý từng cái một để ngăn xếp sẽ chính xác; các )xóa xuống dòng trước, thêm đầu hai yếu tố với nhau, ]xóa các yếu tố trên và phù hợp với nó từ các yếu tố trước trên stack như vậy trừ nó, và>chỉ cần xóa phần tử trên cùng. Cuối cùng, ngăn xếp được chuyển đổi thành số thập phân. Chỉnh sửa: Đã lưu 2 byte nhờ @Leo.


Để làm gì $3? (dù sao thì câu trả lời tuyệt vời!)
Leo

@Leo Đó là một phần còn lại từ một golf trước đó. Cảm ơn vì đã phát hiện ra nó!
Neil

4

Python 3 , 145 144 132 122 116 109 104 byte

-7 byte nhờ Leo!

Và - 5 cảm ơn Lynn!

s=[0]
for i in input().replace('()',' '):s+=i in']>) 'and(i<'!'or(2-ord(i)%5)*s.pop())+s.pop(),
print(s)

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

Thực hiện khá chuẩn. Bây giờ không dễ đọc như vậy. Tôi thất vọng tôi không thể tìm ra một cách ngắn hơn để kiểm tra giữa dấu ngoặc bắt đầu và kết thúc.

Một số nỗ lực tại một lớp lót:

  • 124 byte (hàm ẩn danh):

    lambda c:[s.append(i in']>) 'and(i<'!'or~-']>)'.index(i)*s.pop())+s.pop())or s for s in[[0]]for i in c.replace('()',' ')][0]
  • 115 byte (chương trình đầy đủ):

    s=[0];[s.append(i in']>) 'and(i<'!'or~-']>)'.index(i)*s.pop())+s.pop())for i in input().replace('()',' ')];print(s)

Nối dài khó chịu hơn so với chuyển nhượng đơn giản


~-']>)'.index(i)có thể (2-ord(i)%5)để lưu 4 byte.
Lynn

2

Ruby , 98 91 byte

->s{a=[i=0];s.chars{|c|a<<("([<"[c]?s[i,2]["()"]?1:0:a.pop*~-"]>)".index(c)+a.pop);i+=1};a}

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

Mã ban đầu của tôi hoạt động tương tự theo tinh thần với câu trả lời của Python của Python, để trước khi lặp qua các ký tự nguồn, chúng tôi đã thay thế tất cả các ()chuỗi con bằng một ký tự khác, như là một toán tử riêng biệt.

Tuy nhiên, ít nhất là trong Ruby, hóa ra golfer không làm điều này, mà là một cách tiếp cận rườm rà hơn một chút. Ở đây, chúng tôi duy trì một bộ chỉ mục bổ sung itheo dõi vị trí của chúng tôi trong chuỗi nguồn và bất cứ khi nào gặp phải một khung mở, chúng tôi sẽ kiểm tra xem liệu ký tự hiện tại + tiếp theo của chúng tôi có s[i,2]tạo thành ()toán tử không. Trong trường hợp đó, chúng ta đẩy 1 thay vì 0 trên đầu ngăn xếp và để cho phép đóng )thực hiện công việc của nó trong bước tiếp theo.


1

05AB1E , 25 byte

΄()1:v"0+0\0->"žuykè.V})

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

Giải trình

Î                           # initialize the stack with 0 and the input
 „()1:                      # replace any occurrence of "()" in the input with 1
      v                }    # for each char y in this string
                žuyk        # get its index in the string "()[]<>{}"
       "0+0\0->"    è       # use this to index into the string "0+0\0->"
                     .V     # eval
                        )   # wrap the stack in a list


1

R , 182 177 byte

function(P){for(k in utf8ToInt(gsub("\\(\\)",7,P))%%8){if(k%in%0:4)F=c(0,F)
if(k==7)F[1]=F[1]+1
if(k==1)F=c(F[2]+F[3],F[-3:0])
if(k==5)F=c(F[2]-F[1],F[-2:0])
if(k==6)F=F[-1]}
F}

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

Trả về ngăn xếp, trong đó đỉnh của ngăn xếp là đầu tiên và dưới cùng của ngăn xếp là cuối cùng.

Hoán đổi ()với 7và sau đó tính toán các điểm mã mod 8 để có được các giá trị số riêng biệt, dễ dàng hơn và hoạt động tốt hơn so với chuỗi.

Đó là gôn thủ để làm việc với sự khởi đầu của một vectơ trong R, vì vậy chúng tôi xây dựng ngăn xếp theo cách đó.

Sau đó, nó nhìn thấy một )hoặc khi nào k==1, nó thêm một số 0 vào đỉnh của ngăn xếp vì nó là gôn thủ để thêm nó và loại bỏ nó.


1

CJam , 29 byte

0q")]>([<""+-;U"er"U+"/')*~]p

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

0q                              Push 0, input
  ")]>([<""+-;U"er              Translate )]>([< to +-;UUU
                  "U+"/')*      Replace U+ by )
                          ~     Eval as CJam code
                           ]p   Wrap and pretty-print stack

1

Ceylon, 285 266 byte

function f(variable String c){variable Integer[]s=[0];value o=>[s[0]else nothing,s=s.rest][0];void u(Integer i)=>s=[i,*s];while(c!=""){if(c[0:2]=="()"){u(1);c=c.rest;}switch(c[0])case(')'){u(o+o);}case(']'){u(-o+o);}case('>'){noop(o);}else{u(0);}c=c.rest;}return s;}

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

(Đã lưu 19 byte do đề xuất của Leo.)

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

// Interpreter for ThirdFlak
// Question:    /codegolf//q/163242/2338
// This answer: /codegolf//a/163403/2338
//
// This function takes the code as a string, and returns the value
// of the stack as a sequence of Integers.
function f(variable String c) {
    // stack, in the beginning just a single 0.
    // Top element of the stack is the first, because push + pop is easier this way.
    variable Integer[] s = [0];
    // pop – used like an Integer variable (not a function – this saves the `()`), but has side effects.
    value o =>
        // `s[0]` is the first element of the stack. We tell the compiler
        // that it is non-null (otherwise we'll get an error at run time)
        // using the `else nothing`. `s.rest` is `s` without its first element.
        // Both together are wrapped into a 2-tuple, of which we then take just
        // the first element, to have both together in an expression instead
        // the longer way using an accessor block with a temporary variable and a return.
        // value o {
        //   value r = s[0] else nothing;
        //   s = s.rest;
        //   return r;
        // }
        [s[0] else nothing, s = s.rest][0];
    // push
    void u(Integer i) =>
        // a tuple enumeration, using the spread argument.
        s = [i, *s];
    // the main loop
    while (c != "") {
        if (c[0:2] == "()") {
            // »`()` is the only two-characters operator in Third-Flak. It increases the top of the third stack by 1.«
            // As `)` alone adds the two top elements together, we can just push a one here, and let the handling for `)` do the rest.
            u(1);
            c = c.rest;
        }
        switch (c[0])
        case (')') {
            // »`)` pops two elements from the third stack and pushes back their sum.«
            u(o + o);
        }
        case (']') {
            // »`]` pops two elements from the third stack and pushes back the result of subtracting the first from the second.«
            // As the o written first is the first one, we can't write this as a subtraction.
            u(-o + o);
        }
        case ('>') {
            // »`>` pops an element from the third stack.«
            // `o;` alone is not a valid statement, so we pass it to the `noop` function.
            noop(o);
        }
        else {
            // all other valid code characters are `(`, `[`, `<`, which all just push a 0.
            u(0);
        }
        c = c.rest;
    }
    return s;
}

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


Tôi thực sự không biết Ceylon, nhưng có lẽ bạn có thể xóa trường hợp đầu tiên của công tắc và sử dụng phần khác để quản lý tất cả các dấu ngoặc mở :)
Leo

Hmm, tôi đoán rằng nó có thể hoạt động ... nó sẽ thay đổi hành vi cho đầu vào không hợp lệ, nhưng đó không phải là vấn đề.
Paŭlo Ebermann
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.