Tulislah juru bahasa klasik yang cerdas!

18

Brain-Flak (persilangan antara Brainf ** k dan Flak-Overstow) adalah bahasa esoterik berbasis stack. Sejak tantangan ini diposting, bahasanya telah berevolusi dan diperbarui, tetapi revisi pertama bahasa ini dikenal sebagai "brain-flak classic".

Anda harus menulis sebuah program atau fungsi yang mengambil string kode klasik Brain-Flak, dan mengevaluasinya. Ini juga akan mengambil daftar (mungkin kosong) bilangan bulat. Ada input untuk program klasik Brain-Flak.

Bahasa

Brain-Flak memiliki dua tumpukan, yang dikenal sebagai 'kiri' dan 'kanan'. Tumpukan aktif dimulai dari kiri. Jika tumpukan kosong muncul atau mengintip, itu akan mengembalikan 0. Tidak ada variabel. Saat program dimulai, setiap input didorong ke tumpukan aktif secara berurutan (sehingga input terakhir ada di atas tumpukan).

Satu-satunya karakter yang valid dalam program Brain-Flak adalah ()[]{}<>, dan mereka harus selalu seimbang . Jika ada karakter yang tidak valid, atau tanda kurung tidak cocok, Anda mendapatkan perilaku yang tidak ditentukan. Apa pun itu valid.

Ada dua jenis fungsi: Nilads dan monad . Sebuah nilad adalah fungsi yang mengambil 0 argumen. Ini semua nilad:

  • () +1.
  • [] -1.
  • {} Pop stack aktif.
  • <> Alihkan tumpukan aktif.

Ini digabungkan bersama ketika mereka dievaluasi. Jadi jika kita memiliki '3' di atas tumpukan aktif, cuplikan ini:

()(){}

akan mengevaluasi 1 + 1 + active.pop()yang akan mengevaluasi ke 5. <>mengevaluasi ke 0.

Monad mengambil satu argumen, sepotong kode Brain-Flak. Ini semua monad:

  • (n) Tekan 'n' pada tumpukan aktif.
  • [n] Cetak 'n' sebagai int dan baris baru.
  • {foo}Saat active.peek ()! = 0, lakukan foo. Mengevaluasi ke 0¹.
  • <foo> Jalankan foo, tetapi evaluasilah sebagai 0.

Fungsi-fungsi ini juga akan mengembalikan nilai di dalamnya, jadi

(()()())

Akan mendorong 3 dan

[()()()]

Akan mencetak 3 tetapi

[(()()())]

Akan mencetak dan mendorong 3.

Ketika program selesai dieksekusi, setiap nilai yang tersisa di tumpukan aktif dicetak sebagai integer, dengan baris baru di antaranya. Nilai pada tumpukan lainnya diabaikan.

Aturan:

  • Program Anda harus mendukung angka dalam kisaran (-128, 127), dan ukuran tumpukan minimal 255. Jika Anda mendukung lebih besar, hebat.

  • Underflow / overflow tidak ditentukan.

Sampel IO:

Program kosong:

Input: Tidak Ada

Output: Tidak Ada

Tambahan. Sumber:

({}{})

Memasukkan:

2, 3

Keluaran:

5

Pengurangan. Sumber:

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

Memasukkan:

2, 3

Keluaran:

-1

Perkalian. Sumber:

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

Memasukkan:

7, 8

Keluaran:

56

Fibonacci. Sumber:

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

Memasukkan:

5

Keluaran:

13
8
5
3
2
1
1

Mesin kebenaran

{[({})]}

Celah standar berlaku, dan jawaban tersingkat dalam byte menang.


  • ¹: Ini sebenarnya kesalahan saya. {...} harus mengevaluasi jumlah semua operasinya, yang merupakan IMO salah satu fitur paling keren dari brain-flak. Namun, untuk keperluan tantangan ini, asumsikan yang {...} mengevaluasi sebagai 0.
DJMcMayhem
sumber
Apakah ada aturan mengenai nilai integer minimum yang perlu ditangani oleh program?
0 '
Apa yang {...}mengevaluasi monad ?
Neil
Dalam urutan apa argumen pengurangan? Saya mendapatkan negasi dari apa yang saya harapkan.
Neil
@ Neil Maaf tentang itu. Monad {...}mengevaluasi ke 0. Juga, argumen didorong secara berurutan, sehingga 2didorong, lalu 3didorong, jadi ketika program dimulai, input kedua ( 3) ada di atas tumpukan. Saya akan mengklarifikasi keduanya di pos.
DJMcMayhem

Jawaban:

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

Mengambil daftar input sebagai argumen baris perintah dan kode Brain-Flak dari (garis) stdin. Cobalah online!

Sunting: Menyimpan banyak byte pada pendekatan awal saya dengan beralih ke strategi terjemahan dan evaluasi.

Tidak diikat dan dikomentari

Versi ini juga mencakup beberapa hasil debug yang menunjukkan kode Pip yang dihasilkan dari terjemahan, serta konten tumpukan setelah eksekusi.

;;; 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
DLosc
sumber
Apakah pip lebih baru dari tantangan ini?
DJMcMayhem
@DJMcMayhem Tidak ! Saya juga tidak menggunakan fitur yang lebih baru daripada tantangannya.
DLosc
59

Brain-Flak Classic , 1271 1247 1239 byte

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

Cobalah online!

+4 byte dari memperbaiki bug dengan kondisi di {...}monad, dan -36 byte dari berbagai golf.

1238 byte kode, +1 byte untuk -aflag (yang dapat dikombinasikan dengan flag bahasa).

Ini sekarang dievaluasi {...}sebagai nol per spesifikasi tantangan. Perhatikan bahwa Brain-Flak sendiri telah dievaluasi {...}sebagai jumlah dari semua proses sejak perbaikan bug 7 Mei 2016 dua hari sebelum tantangan ini diposting.

Kode berikut mengartikan Brain-Flak Classic dengan benar, dengan {...}sebagai jumlah dari semua proses. Satu-satunya perbedaan antara kedua penafsir adalah penempatan satu {}nilad.

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

Cobalah online!

Input (ke salah satu penerjemah) adalah program Brain-Flak Classic untuk menafsirkan, kemudian baris baru, kemudian daftar bilangan bulat yang dipisahkan oleh ruang. Tidak ada validasi yang dilakukan pada input. Baris baru diperlukan, bahkan jika program atau input kosong.

Langkah pertama adalah mem-parsing semua input, dimulai dengan tanda kurung:

# 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
}{}<>

Kemudian bilangan bulat diuraikan. Ini biasanya tidak diperlukan, tetapi input diambil sebagai ASCII. Ini memang memiliki garis perak, meskipun: input teks memungkinkan kita untuk menentukan tinggi tumpukan, yang menyederhanakan hal-hal ketika kita tidak memiliki akses ke nilad tinggi tumpukan.

Bilangan bulat diurai menjadi dua angka pada tumpukan kedua: satu untuk nilai absolut, dan satu untuk tanda. Ini kemudian dipindahkan kembali ke tumpukan pertama.

Tumpukan yang ditafsirkan disimpan di bawah kode pada tumpukan pertama dengan urutan sebagai berikut: tinggi tumpukan saat ini, tumpukan saat ini, tinggi tumpukan lainnya, tumpukan lainnya. Angka 0 untuk tinggi tumpukan lainnya tidak perlu ditekan pada titik ini, karena ini akan menjadi nol implisit saat pertama kali dibaca.

(<((

    # 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
>)

Representasi kode sekarang dipindahkan kembali ke tumpukan kiri. Untuk mempermudahnya nanti, kita kurangi 4 dari tanda kurung nilad, sehingga setiap operasi memiliki bilangan bulat unik dari -1 hingga -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
    <>)

<>}<>{}

Bagian utama dari program ini adalah menafsirkan instruksi. Pada awal setiap iterasi dari loop utama, instruksi saat ini adalah di atas tumpukan kiri, semuanya setelah itu di bawahnya pada tumpukan yang sama, dan semuanya sebelum itu berada di tumpukan yang tepat. Saya cenderung membayangkan ini sebagai memiliki buku terbuka ke halaman tertentu.

{

    (

        # 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
        ()){{}(<>)}

    }{}

}

Setelah keluar dari loop utama, semua kode ada di tumpukan kanan. Satu-satunya hal di tumpukan kiri adalah nol dan dua tumpukan ditafsirkan. Memproduksi output yang benar adalah masalah sederhana.

# Pop the zero
{}

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

# Discard other stack to avoid implicit printing
{({}[]<{}>)}{}
Nitrodon
sumber
12
: O apa ... Ok, langsung berhadiah. Pekerjaan yang baik! : D
DJMcMayhem
4
Biarkan saya meluruskan ini ... Anda membuat penerjemah untuk bahasa yang akan ditafsirkan. YoDawg
tisaconundrum
OK, mengapa hanya ada 2 digit nomor upvote?
NieDzejkob
Pekerjaan yang bagus untuk mengimplementasikan akumulator dengan benar {...}, yang merupakan perilaku yang benar untuk brain-flak modern dan (saya pikir) brain-flak classic, namun saya menulis dalam tantangan yang {...}dievaluasi sebagai 0. Anda mungkin bisa bermain golf sejumlah besar byte dengan menghapus fungsionalitas itu, meskipun akan lebih baik untuk menyimpan aslinya karena secara teknis lebih benar secara umum (hanya salah untuk tantangan ini)
DJMcMayhem
@DJMcMayhem Tetap. Hanya saja jangan membuat saya mem-portp seluruh penerjemah ke versi hipotetis 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⍵}

Ini mengambil program sebagai argumen yang tepat, dan input program sebagai argumen kiri, yaitu:

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

Versi tidak disatukan: di sini .

marinus
sumber
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←⍬

Cobalah online!

satu Klasik menafsirkan yang lain :)

ngn
sumber
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())

Digunakan seperti g('[{}{}]', 2, 3)

Ini digunakan re.subuntuk "mengkompilasi" sumber brain-flak ke python dan kemudian mengeksekusi python. (untuk debug, ganti execdengan printuntuk mendapatkan daftar kode python)

Indentasi tersarang dengan benar sementara loop memakan banyak byte dalam kode.

RootTwo
sumber
3

Python, 616 byte

Instruksi:

  1. Jalankan dengan python
  2. Masukkan daftar dalam [1,2,...]format, lalu tekan enter
  3. Rekatkan / tulis program, lalu tekan enter lagi
  4. Selesai

Pada dasarnya, apa yang dilakukan oleh program ini adalah "mengkompilasi" kode Brain-flak secara rekursif ke dalam daftar bersarang, dan secara rekursif menerjemahkan daftar itu. Mungkin ada cara untuk menggabungkan keduanya ...

Saya akan coba dan ulang logika nanti.

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)
Biru
sumber
3

Perl 5.6, 419 414 byte

Saya telah bermain golf sedikit tetapi mungkin ada ruang untuk perbaikan. Baris baru dan tab ditambahkan di sini demi sedikit keterbacaan:

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";
}
Neil
sumber
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

Cobalah online!

-13 byte disimpan berkat @Mr. Xcoder!

DJMcMayhem
sumber