Scrivi un interprete classico squallido!


18

Brain-Flak (un incrocio tra Brainf ** k e Flak-Overstow) è un linguaggio esoterico basato su stack. Da quando è stata pubblicata questa sfida, la lingua si è evoluta e aggiornata, ma questa prima revisione della lingua è nota come "classico cervello-flak".

È necessario scrivere un programma o una funzione che accetta una stringa di codice classico Brain-Flak e lo valuta. Ci vorrà anche un elenco (possibilmente vuoto) di numeri interi. Ci sono gli input per il programma classico Brain-Flak.

La lingua

Brain-Flak ha due pile, conosciute come "sinistra" e "destra". Lo stack attivo inizia a sinistra. Se una pila vuota viene spuntata o sbirciata, restituirà 0. Non ci sono variabili. All'avvio del programma, ogni input viene inserito nello stack attivo in ordine (in modo che l'ultimo input si trovi in ​​cima allo stack).

Gli unici personaggi validi in un programma Brain-Flak sono ()[]{}<>e devono essere sempre bilanciati . Se sono presenti caratteri non validi o le parentesi non corrispondono, si ottiene un comportamento indefinito. Tutto è valido.

Ci sono due tipi di funzioni: Nilads e Monadi . Un nilad è una funzione che accetta 0 argomenti. Ecco tutti i nilad:

  • () +1.
  • [] -1.
  • {} Pop lo stack attivo.
  • <> Attiva / disattiva lo stack attivo.

Questi vengono concatenati insieme quando vengono valutati. Quindi se avessimo un '3' in cima allo stack attivo, questo frammento:

()(){}

valuterebbe a 1 + 1 + active.pop()chi valuterebbe a 5.<> valuta a 0.

Le monadi prendono un argomento, un pezzo di codice Brain-Flak. Ecco tutte le monadi:

  • (n) Premi 'n' sullo stack attivo.
  • [n] Stampa 'n' come int e newline.
  • {foo}Mentre active.peek ()! = 0, fallo. Valuta a 0¹.
  • <foo> Eseguire foo, ma valutarlo come 0.

Queste funzioni restituiranno anche il valore al loro interno, quindi

(()()())

Spingerà 3 e

[()()()]

Stamperà 3 ma

[(()()())]

Stampa e spinge 3.

Al termine dell'esecuzione del programma, ogni valore lasciato nello stack attivo viene stampato come intero, con una nuova riga tra. I valori sull'altro stack vengono ignorati.

Regole:

  • Il programma deve supportare numeri nell'intervallo (-128, 127) e una dimensione dello stack di almeno 255. Se si supporta più grande, ottimo.

  • Underflow / overflow non è definito.

IO di esempio:

Il programma vuoto:

Input: nessuno

Uscita: nessuna

Addizione. Fonte:

({}{})

Ingresso:

2, 3

Produzione:

5

Sottrazione. Fonte:

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

Ingresso:

2, 3

Produzione:

-1

Moltiplicazione. Fonte:

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

Ingresso:

7, 8

Produzione:

56

Fibonacci. Fonte:

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

Ingresso:

5

Produzione:

13
8
5
3
2
1
1

Macchina della verità

{[({})]}

Si applicano scappatoie standard e vince la risposta più breve in byte.


  • ¹: Questo è stato in realtà un errore da parte mia. {...} dovrebbe valutare la somma di tutte le sue corse, che è l'IMO una delle caratteristiche più interessanti del cervello-flak. Tuttavia, ai fini di questa sfida, supponiamo che {...} valuti come 0.

Esiste una regola relativa al valore intero minimo che il programma deve gestire?
0 "

Cosa {...}valuta la monade ?
Neil,

In quale ordine sono gli argomenti di sottrazione? Sto ottenendo la negazione di quello che mi aspetto.
Neil,

@Neil Mi dispiace per quello. La monade {...}valuta 0. Inoltre, gli argomenti vengono spinti in ordine, quindi 2viene spinto, quindi 3viene spinto, quindi quando il programma viene avviato, il secondo input ( 3) è in cima allo stack. Chiarirò entrambi quelli nel post.
DJMcMayhem

Risposte:


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

Prende l'elenco di input come argomenti della riga di comando e il codice Brain-Flak da (una riga di) stdin. Provalo online!

Modifica: ho salvato un sacco di byte sul mio approccio originale passando a una strategia di conversione e valutazione.

Ungolf e commentato

Questa versione include anche alcuni output di debug che mostrano il codice Pip risultante dalla traduzione, nonché i contenuti dello stack dopo l'esecuzione.

;;; 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

Pip è più recente di questa sfida?
DJMcMayhem

@DJMcMayhem No ! Né sto usando alcuna funzionalità più recente della sfida.
DLosc

59

Brain-Flak Classic , 1271 1247 1239 byte

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

Provalo online!

+4 byte dalla correzione di un bug con la condizione in {...} monade e -36 byte da vari golf.

1238 byte di codice, +1 byte per il -a flag (che può essere combinato con il flag di lingua).

Questo ora valuta {...} zero secondo la specifica della sfida. Nota che Brain-Flak stesso ha valutato {...}la somma di tutte le esecuzioni dal bugfix del 7 maggio 2016 due giorni prima che questa sfida fosse pubblicata.

Il codice seguente interpreta Brain-Flak Classic correttamente, con {...}la somma di tutte le esecuzioni. L'unica differenza tra i due interpreti è il posizionamento di un {}nilad.

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

Provalo online!

L'input (per entrambi gli interpreti) è il programma Brain-Flak Classic da interpretare, quindi una nuova riga, quindi un elenco di numeri interi separati da spazi. Non viene eseguita alcuna convalida sull'input. La nuova riga è necessaria, anche se il programma o l'input sono vuoti.

Il primo passo è analizzare tutto l'input, iniziando dalle parentesi:

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

Quindi vengono analizzati gli interi. Questo non sarebbe normalmente necessario, ma l'input è stato preso come ASCII. Questo ha un rivestimento d'argento, tuttavia: l'immissione di testo ci consente di determinare l'altezza della pila, il che semplifica le cose quando non abbiamo accesso all'altezza della pila nilad.

I numeri interi vengono analizzati in due numeri nel secondo stack: uno per il valore assoluto e uno per il segno. Questi vengono quindi riportati al primo stack.

Le pile interpretate vengono memorizzate al di sotto del codice nel primo ordine nel seguente ordine: altezza dello stack corrente, stack corrente, altra altezza dello stack, altro stack. A questo punto non è necessario spingere lo 0 per l'altra altezza dello stack, poiché sarà uno zero implicito la prima volta che viene letto.

(<((

    # 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 rappresentazione del codice viene ora spostata di nuovo nello stack di sinistra. Per facilitare le cose in seguito, sottraggiamo 4 dalle parentesi di apertura di nilad, in modo che ogni operazione abbia un numero intero univoco compreso tra -1 e -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 principale del programma è in realtà l'interpretazione delle istruzioni. All'inizio di ogni iterazione del ciclo principale, l'istruzione corrente si trova nella parte superiore dello stack di sinistra, tutto ciò che segue è sotto di esso nello stesso stack e tutto ciò che è prima di esso è nello stack di destra. Tendo a visualizzarlo come se avesse un libro aperto su una determinata pagina.

{

    (

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

    }{}

}

Dopo essere uscito dal ciclo principale, tutto il codice è nello stack giusto. Le uniche cose nello stack di sinistra sono uno zero e le due pile interpretate. Produrre l'output corretto è una questione semplice.

# Pop the zero
{}

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

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

12
: O che cosa ... Ok, ricompensa immediatamente. Bel lavoro! : D
DJMcMayhem

4
Fammi capire bene ... hai creato un interprete per la lingua che deve essere interpretata. YoDawg
tisaconundrum,

OK, perché ha solo un numero di upgrade di 2 cifre?
NieDzejkob,

Buon lavoro sull'implementazione corretta dell'accumulatore {...}, che è il comportamento corretto per il moderno cervello-flak e (penso) classico cervello-flak, tuttavia ho scritto nella sfida che {...}valuta come 0. Probabilmente potresti golf un numero significativo di byte di rimuovendo tale funzionalità, anche se sarebbe bello mantenere l'originale in giro perché è tecnicamente più corretto in generale (giusto per questa sfida)
DJMcMayhem

@DJMcMayhem Fixed. Non costringermi a portare l'intero interprete a quella ipotetica versione di 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⍵}

Questo prende il programma come argomento giusto e l'input del programma come argomento sinistro, ovvero:

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

Versione non golfata: qui .


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

Provalo online!

un classico interpretando un altro :)


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

Usato come g('[{}{}]', 2, 3)

Viene utilizzato re.subper "compilare" la sorgente del brain-flak in Python e quindi esegue il Python. (per il debug, sostituire execconprint per ottenere un elenco del codice Python)

Il rientro corretto nidificato mentre i loop consuma molti byte nel codice.


3

Python, 616 byte

Istruzioni:

  1. Esegui con Python
  2. Immettere l'elenco in [1,2,...]formato, quindi premere Invio
  3. Incollare / scrivere il programma, quindi premere di nuovo Invio
  4. Fatto

Fondamentalmente, ciò che questo programma fa è "compilare" ricorsivamente il codice Brain-flak in elenchi nidificati e interpretare ricorsivamente tale elenco. C'è probabilmente un modo per combinare i due ...

Proverò a rielaborare la logica in seguito.

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

L'ho giocato un po 'ma probabilmente c'è margine di miglioramento. Newline e schede aggiunte qui per motivi di leggibilità:

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

Provalo online!

-13 byte salvati grazie a @Mr. Xcoder!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.