Viết một thông dịch viên cổ điển não-flak!


18

Brain-Flak (giao thoa giữa Brainf ** k và Flak-Overstow) là ngôn ngữ bí truyền dựa trên ngăn xếp. Kể từ khi thử thách này được đăng, ngôn ngữ đã phát triển và cập nhật, nhưng lần sửa đổi đầu tiên của ngôn ngữ này được gọi là "não kinh điển".

Bạn phải viết một chương trình hoặc hàm lấy một chuỗi mã cổ điển Brain-Flak và đánh giá nó. Nó cũng sẽ lấy một danh sách (có thể trống) các số nguyên. Có những đầu vào cho chương trình cổ điển Brain-Flak.

Ngôn ngữ

Brain-Flak có hai ngăn xếp, được gọi là 'trái' và 'phải'. Ngăn xếp hoạt động bắt đầu ở bên trái. Nếu một ngăn xếp trống được bật hoặc nhìn trộm, nó sẽ trả về 0. Không có biến. Khi chương trình bắt đầu, mỗi đầu vào được đẩy vào ngăn xếp hoạt động theo thứ tự (sao cho đầu vào cuối cùng nằm trên cùng của ngăn xếp).

Các ký tự hợp lệ duy nhất trong chương trình Brain-Flak là ()[]{}<>và chúng phải luôn được cân bằng . Nếu có các ký tự không hợp lệ hoặc dấu ngoặc không khớp, bạn sẽ có hành vi không xác định. Bất cứ điều gì là hợp lệ.

Có hai loại chức năng: NiladsMonads . Một nilad là một hàm có 0 đối số. Dưới đây là tất cả các con số không:

  • () +1.
  • [] -1.
  • {} Pop ngăn xếp hoạt động.
  • <> Chuyển đổi ngăn xếp hoạt động.

Chúng được nối với nhau khi chúng được đánh giá. Vì vậy, nếu chúng tôi có '3' trên đầu ngăn xếp hoạt động, đoạn trích này:

()(){}

sẽ đánh giá để 1 + 1 + active.pop()đánh giá đến 5. <>đánh giá về 0.

Các đơn vị lấy một đối số, một đoạn mã Brain-Flak. Dưới đây là tất cả các đơn nguyên:

  • (n) Nhấn 'n' trên ngăn xếp hoạt động.
  • [n] In 'n' dưới dạng int và một dòng mới.
  • {foo}Trong khi active.peek ()! = 0, hãy thực hiện. Đánh giá về 0¹.
  • <foo> Thực thi foo, nhưng đánh giá nó là 0.

Các hàm này cũng sẽ trả về giá trị bên trong chúng, vì vậy

(()()())

Sẽ đẩy 3 và

[()()()]

Sẽ in 3 nhưng

[(()()())]

Sẽ in đẩy 3.

Khi chương trình được thực thi xong, mỗi giá trị còn lại trên ngăn xếp hoạt động được in dưới dạng một số nguyên, với một dòng mới ở giữa. Các giá trị trên ngăn xếp khác được bỏ qua.

Quy tắc:

  • Chương trình của bạn phải hỗ trợ các số trong phạm vi (-128, 127) và kích thước ngăn xếp ít nhất 255. Nếu bạn hỗ trợ lớn hơn, tuyệt vời.

  • Dòng chảy / tràn không xác định.

Mẫu IO:

Chương trình trống:

Đầu vào: Không có

Đầu ra: Không có

Thêm vào. Nguồn:

({}{})

Đầu vào:

2, 3

Đầu ra:

5

Phép trừ. Nguồn:

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

Đầu vào:

2, 3

Đầu ra:

-1

Phép nhân. Nguồn:

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

Đầu vào:

7, 8

Đầu ra:

56

Xơ. Nguồn:

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

Đầu vào:

5

Đầu ra:

13
8
5
3
2
1
1

Máy thật

{[({})]}

Các sơ hở tiêu chuẩn được áp dụng và câu trả lời ngắn nhất tính theo byte sẽ thắng.


  • : Đây thực sự là một sai lầm của tôi. {...} nên đánh giá tổng của tất cả các hoạt động của nó, đó là IMO một trong những tính năng thú vị nhất của trò chơi trí tuệ. Tuy nhiên, với mục đích của thử thách này, giả sử rằng {...} đánh giá là 0.

Có một quy tắc liên quan đến giá trị số nguyên tối thiểu mà chương trình cần xử lý không?
0 '

Các đơn vị {...}đánh giá để làm gì?
Neil

Theo thứ tự các đối số trừ? Tôi đang nhận được sự phủ nhận của những gì tôi mong đợi.
Neil

@Neil Xin lỗi về điều đó. Đơn vị {...}ước tính là 0. Ngoài ra, các đối số được đẩy theo thứ tự, do đó 2được đẩy, sau đó 3được đẩy, vì vậy khi chương trình bắt đầu, đầu vào thứ hai ( 3) nằm trên cùng của ngăn xếp. Tôi sẽ làm rõ cả hai trong bài.
DJMcMayhem

Câu trả lời:


6

Pip -n , 151 148 101 98 byte

YRVg;VqR^"{}()<>[]";,8R J,8<>2AL,8("POy|i o0Syl1v0W@y{ }1yPU$+[ ]&@y0 1P$+[ ]"R0" (V{"R1"i}) "^s)y

Lấy danh sách các đầu vào dưới dạng đối số dòng lệnh và mã Brain-Flak từ (một dòng) stdin. Hãy thử trực tuyến!

Chỉnh sửa: Đã lưu toàn bộ rất nhiều byte so với cách tiếp cận ban đầu của tôi bằng cách chuyển sang chiến lược dịch và dịch.

Ungolfed và bình luận

Phiên bản này cũng bao gồm một số đầu ra gỡ lỗi hiển thị mã Pip xuất phát từ bản dịch, cũng như nội dung ngăn xếp sau khi thực hiện.

;;; Setup ;;;

; y is the active stack, l is the off-stack
; y is initialized from command-line arguments
y:RVg   (reversed to put the last input at the top)
; l is preset to empty list by default

; p is the program (read from stdin)
p:q

; Translate from braces to numbers 0-7 (we do this so that the
; later replacement step won't try to replace the braces in the
; Pip code)
p R: ^"()[]{}<>" 0,8

;;; Replace nilads with the appropriate code ;;;

; () => o (variable preset to 1)
p R: 01 "o"

; [] => v (variable preset to -1)
p R: 23 "v"

; {} => POy|i
; Pop y; return that value OR i (variable preset to 0)
p R: 45 "POy|i"

; <> => (V{Syli})
; Eval the code Syl to swap stacks y and l, then return i (i.e. 0)
p R: 67 "(V{Syli})"

;;; Replace monads with the appropriate code ;;;

; ( ) => yPU$+[ ]&@y
; Sum ($+) the inside and push (PU) the sum onto y; return
; the just-pushed value, which is the first element of y (@y)
; y will always be truthy (nonempty), since we just pushed a value onto it
p R: 0 "yPU$+["
p R: 1 "]&@y"

; [ ] => P$+[ ]
; Sum ($+) the inside, print (P) the sum, and return it
p R: 2 "P$+["
p R: 3 "]"

; { } => (V{W@y{ }i})
; Eval the code W@y{ }, which wraps the inside in curly braces
; and runs it while (W) the first element of y (@y) is truthy
; (i.e. not zero, and not nil from an empty stack)
; Then return i (i.e. 0)
p R: 4 "(V{W@y{"
p R: 5 "}i})"

; < > => (V{ i})
; Eval the inside, then return i (i.e. 0)
p R: 6 "(V{"
p R: 7 "i})"

; Debug: print the resulting translated code and a blank line
Pp.n

;;; Run the code ;;;

; Eval the translated code
(Vp)

; Output the active stack, newline-separated
PyJn

; Debug: print the active stack and the off-stack
P"Active stack: ".RPy
"Off-stack: ".RPl

Là pip mới hơn thách thức này?
DJMcMayhem

@DJMcMayhem Không ! Tôi cũng không sử dụng bất kỳ tính năng nào mới hơn thử thách.
DLosc

59

Brain-Flak Classic , 1271 1247 1239 byte

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

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

+4 byte từ việc sửa một lỗi với điều kiện trong {...}đơn nguyên và -36 byte từ các sân golf khác nhau.

1238 byte mã, +1 byte cho -acờ (có thể kết hợp với cờ ngôn ngữ).

Điều này bây giờ đánh giá {...}là không cho mỗi đặc điểm kỹ thuật thách thức. Lưu ý rằng chính Brain-Flak đã đánh giá {...}là tổng của tất cả các lần chạy kể từ lỗi ngày 7 tháng 5 năm 2016 hai ngày trước khi thử thách này được đăng.

Đoạn mã sau giải thích chính xác Brain-Flak Classic, với {...}tổng của tất cả các lần chạy. Sự khác biệt duy nhất giữa hai phiên dịch viên là vị trí của một {}nilad.

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

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

Đầu vào (cho một trong hai trình thông dịch) là chương trình Brain-Flak Classic để diễn giải, sau đó là một dòng mới, sau đó là danh sách các số nguyên được phân tách bằng dấu cách. Không có xác nhận được thực hiện trên đầu vào. Dòng mới là bắt buộc, ngay cả khi chương trình hoặc đầu vào trống.

Bước đầu tiên là phân tích tất cả các đầu vào, bắt đầu bằng dấu ngoặc:

# Move to right stack, and push 1 to allow loop to start
<>(())
{
   # While keeping -5 on third stack:
   <>((([][][][][])<

       # Pop bracket or newline k from left stack, and push 0, k-10, k-40, k-60, k-91, k-123 on right stack
       (((({}){})(({})({}))[])({}(({})({}({})({}{}(<>)))))[])

   # Search this list for a zero, and push the number of nonzero entries popped minus 5 
   # (thus replacing the 0 if it was destroyed)
   >{()<{}>}{})

   # Remove rest of list, and push the same number plus 1
   # Result is -4 for {, -3 for [, -2 for <, -1 for (, 0 for newline, or 1 for everything else (assumed closing bracket)
   <{{}}{}>())

# Repeat until newline found
}{}<>

Sau đó, các số nguyên được phân tích cú pháp. Điều này thường sẽ không được yêu cầu, nhưng đầu vào được lấy là ASCII. Mặc dù vậy, điều này có lớp lót bạc: nhập văn bản cho phép chúng tôi xác định chiều cao ngăn xếp, giúp đơn giản hóa mọi thứ khi chúng tôi không có quyền truy cập vào chiều cao ngăn xếp nilad.

Các số nguyên được phân tích thành hai số trên ngăn xếp thứ hai: một cho giá trị tuyệt đối và một cho dấu. Chúng sau đó được chuyển trở lại ngăn xếp đầu tiên.

Các ngăn xếp được giải thích được lưu trữ bên dưới mã trên ngăn xếp đầu tiên theo thứ tự sau: chiều cao ngăn xếp hiện tại, ngăn xếp hiện tại, chiều cao ngăn xếp khác, ngăn xếp khác. 0 cho chiều cao ngăn xếp khác không cần phải được đẩy vào thời điểm này, vì nó sẽ là số 0 ẩn trong lần đầu tiên được đọc.

(<((

    # If stack nonempty, register first stack entry.
    {()(((<>))<>)}{}

    # For each byte k of input:
    {

        # Push -3, -13, and k-32
        <({}(([][][])((({})({}))[]{})){})>

        # Evaluate to 1 if space
        # If not space (32):
        ((){[]<

            # If not minus (45):
            ({}{})((){[]<

                # Replace top of right stack (n) with 10*n + (k-48)
                ({}{}<>((({})({})){}{}){})(<>)

            # Else (i.e., if minus):
            >}{}){

                # Remove excess "else" entry and -3
                {}{}

                # Set sign to negative (and destroy magnitude that shouldn't even be there yet)
                <>(<({}{}())>)(<>)}

        # Else (i.e., if space):
        >}{}){

            # Remove working data for byte, and push two more 0s onto right stack
            (<{}{}{}((<>))<>>)

    # Push number of integers found
    }{}}<>)

    # For each integer:
    <{({}[]<

        # Move magnitude back to left stack
        ({}<>)<>

        # If sign is negative, negate
        {(<{}>)<>{<>({}[])}{}<>({}<>)(<>)}{}

    >)}{}

    # Push stack height onto stack
    <>>)

# Push 0
>)

Việc biểu diễn mã bây giờ được chuyển trở lại ngăn xếp bên trái. Để làm cho mọi thứ dễ dàng hơn sau này, chúng tôi trừ 4 từ dấu ngoặc mở của nilad, để mỗi thao tác có một số nguyên duy nhất từ ​​-1 đến -8.

# For each bracket in the code:
<>{

    # Push k-1 and evaluate to k
    (({}[])()

    # If not closing bracket:
    {

        # Check next bracket (previously checked, since we started at the end here)
        (<{}>)<><(({})[])>

        # Subtract 4 if next bracket is closing bracket
        # Inverting this condition would save 8 bytes here, but cost 12 bytes later.
        [][][][]{()()()()(<{}>)}{}

    <>}{}

    # Push result onto left stack
    <>)

<>}<>{}

Phần chính của chương trình là thực sự diễn giải các hướng dẫn. Khi bắt đầu mỗi lần lặp của vòng lặp chính, lệnh hiện tại nằm ở đầu ngăn xếp bên trái, mọi thứ sau nó nằm dưới nó trên cùng một ngăn xếp và mọi thứ trước khi nó nằm trên ngăn xếp bên phải. Tôi có xu hướng hình dung điều này như có một cuốn sách mở ra một trang nhất định.

{

    (

        # Get current instruction
        ({})

        # Move all code to left stack, and track the current position in code
        <({()<<>({}<>)>}{})>

        # Push -1, signifying that the code will move forward to just before a matching }.
        # In most cases, this will become 0 (do nothing special) before it is acted upon
        ([])

    # Push instruction minus 1
    )

    # If opening bracket:
    ((){[](<

        # Push instruction+1 and instruction+4
        (({}()()(<>))()()())

        # If instruction+4 is nonzero (not loop monad), replace the earlier -1 with 0 to cancel forward seek
        # This would be clearer as {(<{}>)<>(<{}>)<>}, but that would be unnecessarily verbose
        {(<{}>)<>}

    # Else (i.e., if closing bracket):
    >)}{}<>){

# If closing bracket, parse command
# Post-condition for all: if not moving to {, pop two and push evaluation, 0.
# (For nilads, can assume second from top is 0.)
# If moving to {, pop one, push -3, 0, 0.

        # Seven nested if/else statements, corresponding to eight possible instruction.
        # The "else" statements end with 0 already on the stack, so no need to push a 0 except in the innermost if.
        # Each one beyond the first increments the instruction by 1 to compare the result with 0
        # Each instruction will pop the instruction, leaving only its evaluation (with a 0 on top).
        {}((){[]<
        ({}())((){[]<
        ({}())((){[]<
        ({}())((){[]<
        ({}())((){[]<
        ({}())((){[]<
        ({}())((){[](<

            # -7: pop
            # Pop instruction to reveal existing 0 evaluation
            {}

            # Move code out of the way to access stack
            <>{({}<>)<>}{}

            # Duplicate stack height (only useful if stack height is zero)
            (({}))

            (

                # If stack height nonzero
                {

                    # Save stack height on second stack
                    <{}({}<>)<>>

                    # Pop stack
                    {}

                    # Move stack height back and subtract 1
                    (<<>({}[]<>)>)

                }

                # Move code back to normal position
                <><{({}<>)<>}>{}

            # Evaluate as popped entry (0 if nothing popped)
            )

        # (else)
        >)}{}){

            # -6: -1 nilad
            # Just evaluate as -1
            {}{}(<([])>)

        # (else)
        }>}{}){

            # -5: swap nilad
            # Move code out of the way to access stack
            {}<>{({}<>)<>}{}

            # Number of integers to move: stack height + 1 (namely, the stack height and every entry in the stack)
            ((({})())

            # Move to second stack
            <{({}[]<({}<>)<>>)}>{}

            # Do (stack height + 1) times again
            ){({}[]<><

                # Get stack element
                ({}<><

                    # Move alternate (interpreted) stack to second (real) stack, and push length on top of it
                    ({()<({}[]<({}<>)<>>)>}{}<>)

                # Push current stack element below alternate stack
                ><>)

                # Move alternate stack back above newly pushed element
                <>({()<({}[]<({}<>)<>>)>}{}<>)

            >)}

            # Move code back to normal position
            <>(<{({}<>)<>}>)

        # (else)
        }>}{}){

            # -4: 1
            # Just evaluate to 1
            {}{}(<(())>)

        # (else)
        }>}{}){

            # -3: loop
            # Create zero on stack while keeping existing evaluation
            # This becomes (<{}{}>) in the version that meets the challenge spec
            (<{}>)

            # Move code out of the way to access stack
            <>{({}<>)<>}{}

            # Duplicate stack height
            (({}))

            (

                # If stack height nonzero
                {

                    # Save stack height on second stack
                    <{}({}<>)<>>

                    # Peek at top of stack
                    ({})

                    # Move stack height back
                    (<<>({}<>)>)

                }

                # Move code back to normal position
                <><{({}<>)<>}>

            # Look at peeked entry
            # Remove the {} in the version meeting the challenge spec
            {})

            # If peeked entry is nonzero
            {

                # Replace -3 instruction on third stack
                {}([][][])

                # Replace loop indicator to 0 (to be incremented later to 1)
                <>(((<{}>)

                # Create dummy third stack entry to pop
                <>))

            }

        # (else)
        }>}{}){

            # -2: print
            # Just print evaluation without modifying it
            {}(<([{}])>)

        # (else)
        }>}{}){

            # -1: evaluate as zero
            # Just change evaluation to 0
            {}((<{}>))

        # else
        }>}{}){

            # 0: push
            # Get current evaluation (without modifying it)
            {}(({})

                # Create zero on stack as barrier
                (<()>)

                # Move code out of the way to access stack
                <<>{({}<>)<>}{}

                # Increment stack height and save on other stack
                ({}()<>)<>

            # Push evaluation
            >)

            # Move stack height back (and push zero)
            <>(<({}<>)>)

            # Move code back to normal position
            <>{({}<>)<>}

        }{}

        # Update third stack by adding evaluation to previous entry's evaluation
        # Previous entry's instruction is saved temporarily on left stack
        (<({}<({}<>)<>>{})<>({}<>)>)

        # Increment loop indicator
        # If instruction was loop monad and top of stack was nonzero, this increments 0 to 1 (search backward)
        # Otherwise, this increments -1 to 0 (do nothing)
        <>(<({}())>)

    }{}

    # While holding onto loop indicator
    ({}<

        # Go to immediately after executed symbol
        {({}[]<({}<>)<>>)}{}

    >)

    # If looping behavior:
    {

        # Switch stack and check if searching forward
        ((({}[]<>)

        # If so:
        {

            # Move just-executed { back to left stack, and move with it
            (<{}({}<>)>)

        }{}

        # Either way, we are currently looking at the just-executed bracket.
        # In addition, the position we wish to move to is on the current stack.

        # Push unmodified loop indicator as initial value in search
        ())

        # While value is nonzero:
        <{

            # Add 1
            ({}()

                # Move current instruction to other stack
                <({}<>)<>

                # Check whether next instruction is closing bracket
                (({})[])>

                # If opening bracket, subtract 2 from value
                {[][](<{}>)}{}

            )

        }{}>

        # If searching backward, move back to left stack
        ()){{}(<>)}

    }{}

}

Sau khi thoát khỏi vòng lặp chính, tất cả các mã nằm trên ngăn xếp bên phải. Thứ duy nhất trên ngăn xếp bên trái là số 0 và hai ngăn xếp được giải thích. Sản xuất đầu ra chính xác là một vấn đề đơn giản.

# Pop the zero
{}

# Output current stack
{({}[]<[{}]>)}{}

# Discard other stack to avoid implicit printing
{({}[]<{}>)}{}

12
: O những gì ... Ok, tiền thưởng ngay lập tức. Công việc tốt! : Đ
DJMcMayhem

4
Hãy để tôi nói thẳng điều này ... bạn đã tạo một trình thông dịch cho ngôn ngữ sẽ được thông dịch. YoDawg
tisaconundrum

OK, tại sao nó chỉ có một số upvote 2 chữ số?
NieDzejkob

Làm tốt công việc triển khai chính xác bộ tích lũy {...}, đó là hành vi đúng cho flak não hiện đại và (tôi nghĩ) cổ điển về não, tuy nhiên tôi đã viết trong thử thách {...}đánh giá là 0. Bạn có thể chơi golf với số lượng byte đáng kể bằng cách loại bỏ chức năng đó, mặc dù sẽ rất tốt nếu giữ nguyên bản gốc vì nói chung về mặt kỹ thuật thì đúng hơn (chỉ sai cho thử thách này)
DJMcMayhem

@DJMcMayhem Đã sửa. Đừng bắt tôi chuyển toàn bộ phiên dịch sang phiên bản giả thuyết đó của Brain-Flak.
Nitrodon

8

APL, 255 257 byte

b←{S←(⌽⍺)⍬
e←{0=⍴⍵:0
v+∇⊃_ v←∇{r←⊂2↓⍵
'()'≡n←2↑⍵:r,1
'[]'≡n:r,¯1
'{}'≡n:r,{i←⊃⊃⊃S⋄S[1]↓⍨←1⋄i}⍬
'<>'≡n:r,0⊣S⌽⍨←1
r←⊂⍵↓⍨i←0⍳⍨(+\c=⍵)-+\')]>}'['([<{'⍳c←⊃⍵]=⍵
i←1↓¯1↓c←i↑⍵
'('=c←⊃c:r,S[1],⍨←⍺⍺i
'['=c:r,+⎕←⍺⍺i
'{'=c:r,{0≠⊃⊃⊃S:∇e i⋄0}⍬
'<'=c:r,0⊣⍺⍺i}⍵}
⎕←⍪⊃S⊣e⍵}

Điều này lấy chương trình làm đối số bên phải và đầu vào chương trình làm đối số bên trái, nghĩa là:

      2 3 b '({}{})'
5
      2 3 b '({}<>){({}[])<>({}[])<>}<>'
¯1
      7 8 b '({}<>)<>({}[]){({}[])<>(({}))<>}<>{({}<>{})<>}<>'
56
      5 b '<>((()))<>{({}[])<>({}<>)<>(({})<>({}<>))<>}<>'
13
 8
 5
 3
 2
 1
 1

Phiên bản bị đánh cắp: tại đây .


7

APL (Dyalog Classic) , 146 byte

↑⍕¨s⊣{⍎⍕1 ¯1'(s↓⍨←1)⊢⊃s' '0⊣s t←t s' 's,⍨←+/∇¨a' '⎕←+/∇¨a' '∇{×⊃s:∇⍺⍺¨a⋄0}0' '0⊣+/∇¨a'[(⊃⍵)+4×⍬≢a1↓⍵]}¨⍎∊(')',⍨'(',¨⍕¨⍳4)[0,4,⍨'([{<'⍳⍞]⊣s←⌽⎕⊣t←⍬

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

một cổ điển diễn giải khác :)


6

Python 3, 429 byte

import re
S='s+=[v];v=0';T='v+=s.pop()';i=0
d={'()':'v+=1','(':S,')':'a+=[v];'+T,'[]':'v-=1','[':S,']':'print(v);'+T,'<>':'a.reverse()','<':S,'>':T,'{}':'v+=0if a[-1]==""else a.pop()','{':S+';while a[-1]:','}':T}
def r(m):global i;t=m.group();i-=(t=='}');s=' '*i;i+=(t=='{');return''.join(s+r+'\n'for r in d[t].split(';'))
def g(c,*a):
 a,s,v=['']+list(a),[],0;exec(re.sub(r'[<({[]?[]})>]?',r,c));
 while a[-1]!="":print(a.pop())

Được sử dụng như g('[{}{}]', 2, 3)

Nó sử dụng re.subđể "biên dịch" nguồn flak não cho trăn và sau đó thực thi con trăn. (để gỡ lỗi, thay thếexec gỡ lỗi bằng printđể có danh sách mã python)

Việc thụt lề đúng cách lồng nhau trong khi các vòng lặp ăn rất nhiều byte trong mã.


3

Python, 616 byte

Hướng dẫn:

  1. Chạy với trăn
  2. Danh sách đầu vào trong [1,2,...] định dạng, sau đó nhấn enter
  3. Dán / ghi chương trình, sau đó nhấn enter lần nữa
  4. Làm xong

Về cơ bản, những gì chương trình này làm là đệ quy "biên dịch" mã Brain-flak thành các danh sách lồng nhau và diễn giải đệ quy danh sách đó. Có lẽ có một cách để kết hợp cả hai ...

Tôi sẽ thử và làm lại logic sau.

y="([{<)]}>"
w,z,g=print,len,input
def c(s):
 if z(s)<1:return[]
 t,i,o=[],1,0
 t.append(y.index(s[0]))
 while z(t)>0:
  x=y.index(s[i])
  if x<4:t.append(x)
  else:o=t.pop()
  i+=1
 r=[[o,c(s[1:i-1])]]
 r.extend(c(s[i:]))
 return r
p=lambda t:t.pop()if z(t)>0 else 0
k=lambda t:t[z(t)-1]if z(t)>0 else 0
r,l=[],eval(g())
a=l
def i(u):
 v=0
 global a
 for t,n in u:
  if t<1:
   if n:o=i(n);v+=o;a.append(o)
   else:v+=1
  if t==1:
   if n:o=i(n);v+=o;w(o)
   else:v-=1
  if t==2:
   if n:
    while k(a)!=0:i(n)
   else:v+=p(a)
  if t>2:
   if n:i(n)
   elif a==l:a=r
   else:a=l
 return v
i(c(g()))
for n in a:w(n)

3

Perl 5.6, 419 414 byte

Tôi đã đánh gôn một chút nhưng có lẽ có phạm vi để cải thiện. Các dòng mới và các tab được thêm vào đây vì mục đích dễ đọc:

use Text::Balanced extract_bracketed;
$s=shift;
@a=reverse@ARGV;
sub p
{
    my($c)=@_;
    my$s=0;
    while(my$n=extract_bracketed($c)){
        $s+='()'eq$n||'{}'eq$n&&shift@a;
        $s-='[]'eq$n;
        @t=@a,@a=@i,@i=@t if'<>'eq$n;
        my$m=chop($n);
        $n=substr($n,1);
        if($n){
            p($n)while'}'eq$m&&$a[0];
            p($n)if'}'ne$m;
            $s+=$v,unshift@a,$v if')'eq$m;
            $s+=$v,print"n=$n m=$m v=$v\n"if']'eq$m;
        }
    }
    $v=$s;
}
p($s);
foreach(@a){
    print"$_\n";
}

1

Python 2 , 361 , 348 byte

c,s=input();s=s,[]
a=s[0]
def w():global a,s;s=s[::-1];a=s[0];return 0
def p(c):a.append(c);return c
def n(c):print c;return c
z=lambda c:0
def l(f):
 global a
 while a and a[-1]:f()
 return 0
for x,y in zip("() ( [] {} <> [ < { } ] >".split(),"+1 +p( -1 +(len(a)and(a.pop())) +w() +n( +z( +l(lambda: ) ) )".split()):c=c.replace(x,y)
exec c
print a

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

-13 byte được lưu nhờ vào @Mr. Xcoder!

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.