Schreiben Sie einen klassischen Dolmetscher der Superlative!


18

Brain-Flak (eine Kreuzung zwischen Brainf ** k und Flak-Overstow) ist eine stapelbasierte esoterische Sprache. Seitdem diese Herausforderung veröffentlicht wurde, hat sich die Sprache weiterentwickelt und aktualisiert, aber diese erste Überarbeitung der Sprache ist als "Brain-Flak-Klassiker" bekannt.

Sie müssen ein Programm oder eine Funktion schreiben, die eine Zeichenfolge aus klassischem Brain-Flak-Code verwendet und auswertet. Es wird auch eine (möglicherweise leere) Liste von ganzen Zahlen erstellt. Es gibt die Eingänge zum klassischen Programm von Brain-Flak.

Die Sprache

Brain-Flak hat zwei Stapel, die als "links" und "rechts" bekannt sind. Der aktive Stapel beginnt links. Wenn ein leerer Stapel abgefallen ist, wird 0 zurückgegeben. Es gibt keine Variablen. Wenn das Programm startet, wird jede Eingabe der Reihe nach auf den aktiven Stapel gelegt (so dass die letzte Eingabe über dem Stapel liegt).

Die einzigen gültigen Zeichen in einem Brain-Flak-Programm sind ()[]{}<>, und sie müssen immer ausgeglichen sein . Wenn ungültige Zeichen vorhanden sind oder die Klammern nicht übereinstimmen, tritt undefiniertes Verhalten auf. Alles ist gültig.

Es gibt zwei Arten von Funktionen: Niladen und Monaden . Ein Nilad ist eine Funktion, die 0 Argumente akzeptiert . Hier sind alle Niladen:

  • () +1.
  • [] -1.
  • {} Pop den aktiven Stapel.
  • <> Schaltet den aktiven Stapel um.

Diese werden bei der Auswertung miteinander verkettet. Wenn wir also eine '3' über dem aktiven Stapel hatten, lautet dieser Ausschnitt:

()(){}

würde auswerten, zu 1 + 1 + active.pop()welcher würde auswerten, zu 5. <>auswertet, zu 0.

Die Monaden nehmen ein Argument, einen Teil des Brain-Flak-Codes. Hier sind alle Monaden:

  • (n) Drücken Sie 'n' auf dem aktiven Stapel.
  • [n] 'N' als Int und Newline ausgeben.
  • {foo}Während active.peek ()! = 0 ist, mach foo. Wertet auf 0¹ aus.
  • <foo> Foo ausführen, aber mit 0 bewerten.

Diese Funktionen geben also auch den Wert in ihnen zurück

(()()())

Drücke 3 und

[()()()]

Druckt aber 3

[(()()())]

Druckt und drückt 3.

Wenn das Programm ausgeführt ist, wird jeder auf dem aktiven Stapel verbleibende Wert als Ganzzahl mit einem Zeilenumbruch zwischen gedruckt. Werte auf dem anderen Stapel werden ignoriert.

Regeln:

  • Ihr Programm muss Zahlen im Bereich (-128, 127) und eine Stapelgröße von mindestens 255 unterstützen. Wenn Sie größere unterstützen, ist dies großartig.

  • Unterlauf / Überlauf ist undefiniert.

Beispiel IO:

Das leere Programm:

Eingabe: Keine

Ausgabe: Keine

Zusatz. Quelle:

({}{})

Eingang:

2, 3

Ausgabe:

5

Subtraktion. Quelle:

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

Eingang:

2, 3

Ausgabe:

-1

Multiplikation. Quelle:

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

Eingang:

7, 8

Ausgabe:

56

Fibonacci. Quelle:

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

Eingang:

5

Ausgabe:

13
8
5
3
2
1
1

Wahrheitsmaschine

{[({})]}

Es gelten Standardlücken, und die kürzeste Antwort in Bytes gewinnt.


  • ¹: Das war tatsächlich ein Fehler von meiner Seite. {...} sollte die Summe aller seiner Läufe auswerten, was meiner Meinung nach eines der coolsten Features von Brain-Flak ist. Nehmen Sie jedoch für die Zwecke dieser Abfrage an, dass {...} als 0 ausgewertet wird.

Gibt es eine Regel bezüglich des minimalen Integerwerts, den das Programm verarbeiten muss?
0 '

Was {...}wertet die Monade aus ?
Neil

In welcher Reihenfolge sind die Subtraktionsargumente? Ich bekomme die Verneinung dessen, was ich erwarte.
Neil

@Neil Tut mir leid. Die Monade wird {...}mit 0 bewertet. Außerdem werden die Argumente der Reihe nach gepusht, also 2wird gepusht und dann 3gepusht. Wenn das Programm gestartet wird, befindet sich die zweite Eingabe ( 3) oben auf dem Stapel. Ich werde beide in der Post klären.
DJMcMayhem

Antworten:


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

Übernimmt die Liste der Eingaben als Befehlszeilenargumente und den Brain-Flak-Code aus (einer Zeile von) stdin. Probieren Sie es online!

Bearbeiten: Durch den Wechsel zu einer Übersetzungs- und Evaluierungsstrategie wurden viele Bytes gegenüber meinem ursprünglichen Ansatz gespart.

Ungolfed und kommentiert

Diese Version enthält auch einige Debug-Ausgaben, die den aus der Übersetzung resultierenden Pip-Code sowie den Stapelinhalt nach der Ausführung anzeigen.

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

Ist pip neuer als diese Herausforderung?
DJMcMayhem

@DJMcMayhem Nein ! Ich verwende auch keine Funktionen, die neuer sind als die Herausforderung.
DLosc

59

Brain-Flak Classic , 1271 1247 1239 Bytes

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

Probieren Sie es online!

+4 Bytes vom Beheben eines Fehlers mit der Bedingung in der {...}Monade und -36 Bytes von verschiedenen Golfplätzen.

1238 Byte Code, +1 Byte für das -aFlag (das mit dem Sprachflag kombiniert werden kann).

Dies wird nun {...}gemäß der Herausforderungsspezifikation als Null bewertet . Beachten Sie, dass Brain-Flak selbst {...}als Summe aller Läufe seit dem Bugfix vom 7. Mai 2016 zwei Tage vor Veröffentlichung dieser Herausforderung ausgewertet wurde.

Der folgende Code interpretiert Brain-Flak Classic korrekt {...}als die Summe aller Läufe. Der einzige Unterschied zwischen den beiden Dolmetschern ist die Platzierung einer {}Null.

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

Probieren Sie es online!

Eingabe (für jeden Interpreter) ist das zu interpretierende Brain-Flak Classic-Programm, dann eine neue Zeile und dann eine durch Leerzeichen getrennte Liste von ganzen Zahlen. Für die Eingabe wird keine Validierung durchgeführt. Die neue Zeile ist erforderlich, auch wenn das Programm oder die Eingabe leer ist.

Der erste Schritt ist das Parsen aller Eingaben, beginnend mit den Klammern:

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

Dann werden die ganzen Zahlen analysiert. Dies wäre normalerweise nicht erforderlich, aber die Eingabe wurde als ASCII-Zeichen verwendet. Dies hat jedoch einen silbernen Strich: Die Texteingabe ermöglicht es uns, die Stapelhöhe zu bestimmen, was die Dinge vereinfacht, wenn wir keinen Zugriff auf die Stapelhöhe Null haben.

Ganzzahlen werden im zweiten Stapel in zwei Zahlen zerlegt: eine für den absoluten Wert und eine für das Vorzeichen. Diese werden dann zurück zum ersten Stapel verschoben.

Die interpretierten Stapel werden unter dem Code auf dem ersten Stapel in der folgenden Reihenfolge gespeichert: aktuelle Stapelhöhe, aktueller Stapel, andere Stapelhöhe, anderer Stapel. Die 0 für die andere Stapelhöhe muss an dieser Stelle nicht verschoben werden, da sie beim ersten Lesen eine implizite Null ist.

(<((

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

Die Darstellung des Codes wird nun wieder in den linken Stapel verschoben. Um es später einfacher zu machen, subtrahieren wir 4 von den öffnenden Klammern der Nullen, sodass jede Operation eine eindeutige Ganzzahl von -1 bis -8 hat.

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

<>}<>{}

Der Hauptteil des Programms ist die Interpretation der Anweisungen. Zu Beginn jeder Iteration der Hauptschleife befindet sich der aktuelle Befehl oben auf dem linken Stapel, alles, was sich darunter befindet, auf demselben Stapel und alles, was sich davor auf dem rechten Stapel befindet. Ich neige dazu, mir vorzustellen, dass ein Buch für eine bestimmte Seite geöffnet ist.

{

    (

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

    }{}

}

Nach dem Verlassen der Hauptschleife befindet sich der gesamte Code auf dem rechten Stapel. Die einzigen Dinge auf dem linken Stapel sind eine Null und die beiden interpretierten Stapel. Es ist ganz einfach, die richtige Ausgabe zu erstellen.

# Pop the zero
{}

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

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

12
: O was zum ... Ok, sofort belohnen. Gute Arbeit! : D
DJMcMayhem

4
Lassen Sie mich das klarstellen ... Sie haben einen Dolmetscher für die zu interpretierende Sprache erstellt. YoDawg
tisaconundrum

OK, warum hat es nur eine zweistellige Upvote-Nummer?
NieDzejkob

Gute Arbeit bei der korrekten Implementierung des Akkumulators in {...}, das ist das korrekte Verhalten für moderne Brain-Flak- und (ich denke) Brain-Flak-Klassiker, aber ich habe in der Herausforderung geschrieben, dass{...} die mit 0 bewertet wird durch Entfernen dieser Funktionalität, obwohl es schön wäre, das Original zu behalten, da es im Allgemeinen technisch korrekter ist (nur falsch für diese Herausforderung)
DJMcMayhem

@DJMcMayhem Behoben. Lassen Sie mich nur nicht den gesamten Interpreten auf diese hypothetische Version von Brain-Flak portieren.
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⍵}

Dies nimmt das Programm als rechtes Argument und die Programmeingabe als linkes Argument, dh:

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

Ungolfed-Version: hier .


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

Probieren Sie es online!

ein Klassiker interpretiert einen anderen :)


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

Gebraucht wie g('[{}{}]', 2, 3)

Es wird verwendet re.sub, um die Brain-Flak-Quelle in Python zu "kompilieren" und dann das Python auszuführen. (für Debugging, ersetzen execmitprint einer Auflistung des Python - Code zu bekommen)

Wenn verschachtelte while-Schleifen ordnungsgemäß eingerückt werden, werden viele Bytes im Code verbraucht.


3

Python, 616 Bytes

Anleitung:

  1. Führen Sie mit Python
  2. Eingabeliste in [1,2,...] Format ein und drücken Sie die Eingabetaste
  3. Programm einfügen / schreiben und erneut die Eingabetaste drücken
  4. Getan

Grundsätzlich "kompiliert" dieses Programm den Brain-Flak-Code rekursiv in verschachtelte Listen und interpretiert diese Liste rekursiv. Es gibt wahrscheinlich eine Möglichkeit, die beiden zu kombinieren ...

Ich werde später versuchen, die Logik zu überarbeiten.

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 Bytes

Ich habe ein bisschen Golf gespielt, aber es gibt wahrscheinlich Raum für Verbesserungen. Hier wurden Zeilenumbrüche und Tabulatoren hinzugefügt, um die Lesbarkeit zu verbessern:

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

Probieren Sie es online!

-13 Bytes gespart dank @Mr. Xcoder!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.