¡Escriba un intérprete clásico de cerebro-flak!

18

Brain-Flak (un cruce entre Brainf ** k y Flak-Overstow) es un lenguaje esotérico basado en la pila. Desde que se publicó este desafío, el lenguaje ha evolucionado y actualizado, pero esta primera revisión del lenguaje se conoce como "clásico de ataque cerebral".

Debe escribir un programa o función que tome una cadena de código clásico Brain-Flak y lo evalúe. También tomará una lista (posible vacía) de enteros. Hay entradas para el programa clásico Brain-Flak.

El idioma

Brain-Flak tiene dos pilas, conocidas como 'izquierda' y 'derecha'. La pila activa comienza a la izquierda. Si aparece o se mira una pila vacía, devolverá 0. No hay variables. Cuando se inicia el programa, cada entrada se inserta en la pila activa en orden (de modo que la última entrada esté en la parte superior de la pila).

Los únicos caracteres válidos en un programa Brain-Flak son ()[]{}<>, y siempre deben estar equilibrados . Si hay caracteres no válidos o los corchetes no coinciden, obtendrá un comportamiento indefinido. Todo es valido.

Hay dos tipos de funciones: Nilads y Mónadas . Un nilad es una función que toma 0 argumentos. Aquí están todas las nilas:

  • () +1.
  • [] -1.
  • {} Pop la pila activa.
  • <> Alternar la pila activa.

Estos se concatenan juntos cuando se evalúan. Entonces, si tuviéramos un '3' en la parte superior de la pila activa, este fragmento:

()(){}

evaluaría a 1 + 1 + active.pop()cuál evaluaría a 5. <>evalúa a 0.

Las mónadas toman un argumento, un trozo de código Brain-Flak. Aquí están todas las mónadas:

  • (n) Presione 'n' en la pila activa.
  • [n] Imprima 'n' como int y newline.
  • {foo}Mientras active.peek ()! = 0, haz foo. Evalúa a 0¹.
  • <foo> Ejecute foo, pero evalúelo como 0.

Estas funciones también devolverán el valor dentro de ellas, por lo que

(()()())

Empujará 3 y

[()()()]

Imprimirá 3 pero

[(()()())]

Imprimirá y empujará 3.

Cuando el programa termina de ejecutarse, cada valor que queda en la pila activa se imprime como un entero, con una nueva línea entre ellos. Los valores en la otra pila se ignoran.

Reglas:

  • Su programa debe admitir números en el rango (-128, 127) y un tamaño de pila de al menos 255. Si admite más grande, excelente.

  • Underflow / overflow no está definido.

Muestra IO:

El programa vacío:

Entrada: ninguna

Salida: ninguna

Adición. Fuente:

({}{})

Entrada:

2, 3

Salida:

5

Sustracción. Fuente:

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

Entrada:

2, 3

Salida:

-1

Multiplicación. Fuente:

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

Entrada:

7, 8

Salida:

56

Fibonacci Fuente:

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

Entrada:

5

Salida:

13
8
5
3
2
1
1

Máquina de la verdad

{[({})]}

Se aplican las lagunas estándar y gana la respuesta más corta en bytes.


  • ¹: Esto fue realmente un error de mi parte. {...} debe evaluar la suma de todas sus ejecuciones, que es IMO una de las mejores características de brain-flak. Sin embargo, para los propósitos de este desafío, suponga que se {...} evalúa como 0.
DJMcMayhem
fuente
¿Existe una regla sobre el valor entero mínimo que el programa necesita manejar?
0 '
¿Qué {...}evalúa la mónada ?
Neil
¿En qué orden están los argumentos de resta? Me está negando lo que espero.
Neil
@Neil Lo siento por eso. La mónada se {...}evalúa a 0. Además, los argumentos se ordenan, por lo que2 se empuja, luego 3se empuja, de modo que cuando se inicia el programa, la segunda entrada ( 3) está en la parte superior de la pila. Aclararé a los dos en la publicación.
DJMcMayhem

Respuestas:

6

Pip -n , 151 148 101 98 bytes

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

Toma la lista de entradas como argumentos de línea de comandos y el código Brain-Flak de (una línea de) stdin. Pruébalo en línea!

Editar: guardé una gran cantidad de bytes sobre mi enfoque original al cambiar a una estrategia de traducir y evaluar.

Ungolfed y comentó

Esta versión también incluye algunos resultados de depuración que muestran el código Pip que resulta de la traducción, así como el contenido de la pila después de la ejecució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
DLosc
fuente
¿El pip es más nuevo que este desafío?
DJMcMayhem
@DJMcMayhem ¡ No ! Tampoco estoy usando ninguna característica más nueva que el desafío.
DLosc
59

Brain-Flak Classic , 1271 1247 1239 bytes

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

Pruébalo en línea!

+4 bytes de arreglar un error con la condición en el {...} mónada, y -36 bytes de varios campos de golf.

1238 bytes de código, +1 byte para el -a indicador (que se puede combinar con el indicador de idioma).

Esto ahora evalúa {...} como cero según la especificación de desafío. Tenga en cuenta que Brain-Flak se ha evaluado {...}como la suma de todas las ejecuciones desde la corrección de errores del 7 de mayo de 2016 dos días antes de que se publicara este desafío.

El siguiente código interpreta Brain-Flak Classic correctamente, con {...}la suma de todas las ejecuciones. La única diferencia entre los dos intérpretes es la colocación de una {}nilad.

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

Pruébalo en línea!

La entrada (a cualquiera de los intérpretes) es el programa Brain-Flak Classic para interpretar, luego una nueva línea, luego una lista de enteros separados por espacios. No se realiza validación en la entrada. Se requiere la nueva línea, incluso si el programa o la entrada están en blanco.

El primer paso es analizar toda la entrada, comenzando con los corchetes:

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

Luego se analizan los enteros. Esto normalmente no sería necesario, pero la entrada se tomó como ASCII. Sin embargo, esto tiene un lado positivo: el ingreso de texto nos permite determinar la altura de la pila, lo que simplifica las cosas cuando no tenemos acceso a la altura de la pila nilad.

Los enteros se analizan en dos números en la segunda pila: uno para el valor absoluto y otro para el signo. Estos se mueven de nuevo a la primera pila.

Las pilas interpretadas se almacenan debajo del código en la primera pila en el siguiente orden: altura de pila actual, pila actual, otra altura de pila, otra pila. El 0 para la otra altura de la pila no necesita ser empujado en este punto, ya que será un cero implícito la primera vez que se lea.

(<((

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

La representación del código ahora se mueve de regreso a la pila izquierda. Para facilitar las cosas más adelante, restamos 4 de los corchetes de apertura de nilads, para que cada operación tenga un número entero único de -1 a -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
    <>)

<>}<>{}

La parte principal del programa es interpretar las instrucciones. Al comienzo de cada iteración del bucle principal, la instrucción actual está en la parte superior de la pila izquierda, todo lo que está debajo está en la misma pila, y todo lo que está antes en la pila derecha. Tiendo a visualizar esto como si tuviera un libro abierto en una página determinada.

{

    (

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

    }{}

}

Después de salir del bucle principal, todo el código está en la pila correcta. Las únicas cosas en la pila izquierda son un cero y las dos pilas interpretadas. Producir la salida correcta es una cuestión simple.

# Pop the zero
{}

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

# Discard other stack to avoid implicit printing
{({}[]<{}>)}{}
Nitrodon
fuente
12
: O qué demonios ... Ok, generoso de inmediato. ¡Buen trabajo! : D
DJMcMayhem
44
Permítanme aclarar esto ... usted creó un intérprete para el idioma que se interpretará. YoDawg
tisaconundrum
OK, ¿por qué solo tiene un número de votación de 2 dígitos?
NieDzejkob
Buen trabajo en la implementación correcta del acumulador {...}, que es el comportamiento correcto para el clásico cerebro-flak moderno y (creo) cerebro-flak clásico, sin embargo, escribí en el desafío que {...}evalúa como 0. Probablemente podría jugar un número significativo de bytes de eliminando esa funcionalidad, aunque sería bueno mantener el original alrededor porque es técnicamente más correcto en general (simplemente incorrecto para este desafío)
DJMcMayhem
@DJMcMayhem Fijo. Simplemente no me hagas portar al intérprete completo a esa versión hipotética de Brain-Flak.
Nitrodon
8

APL, 255 257 bytes

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⍵}

Esto toma el programa como su argumento derecho, y la entrada del programa como su argumento izquierdo, es decir:

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

Versión sin golf: aquí .

marinus
fuente
7

APL (Dyalog Classic) , 146 bytes

↑⍕¨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←⍬

Pruébalo en línea!

un clásico interpretando otro :)

ngn
fuente
6

Python 3, 429 bytes

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

Utilizado como g('[{}{}]', 2, 3)

Se utiliza re.subpara "compilar" la fuente de ataque cerebral a Python y luego ejecuta la pitón. (para depurar, reemplace execcon printpara obtener una lista del código de Python)

La sangría adecuada anidada mientras los bucles consume muchos bytes en el código.

RootTwo
fuente
3

Python, 616 bytes

Instrucciones:

  1. Corre con python
  2. Ingrese la lista en [1,2,...]formato, luego presione enter
  3. Pegar / escribir programa, luego presione enter nuevamente
  4. Hecho

Básicamente, lo que hace este programa es "compilar" recursivamente el código Brain-flak en listas anidadas e interpretar esa lista recursivamente. Probablemente hay una manera de combinar los dos ...

Trataré de reelaborar la lógica más tarde.

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)
Azul
fuente
3

Perl 5.6, 419414 bytes

Lo he jugado un poco, pero probablemente hay margen de mejora. Nuevas líneas y pestañas agregadas aquí en aras de un poco de legibilidad:

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
fuente
1

Python 2 , 361 , 348 bytes

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

Pruébalo en línea!

-13 bytes guardados gracias a @Mr. Xcoder!

DJMcMayhem
fuente