Напишіть перекладач класичного мозку!


18

Мозок-Флак (перехрестя між Brainf ** k та Flak-Overstow) - езотерична мова на основі стека. З моменту оприлюднення цього виклику мова розвивалася та оновлювалася, але ця перша редакція мови відома як "класика, що пролягає".

Ви повинні написати програму або функцію, яка приймає рядок класичного коду Brain-Flak та оцінює її. Він також візьме (можливий порожній) список цілих чисел. Є входи до класичної програми Brain-Flak.

Мова

Brain-Flak має дві стеки, відомі як "лівий" і "правий". Активний стек починається зліва. Якщо порожній стек вискакує або підгляне, він поверне 0. Змінні немає. Коли програма запускається, кожен вхід висувається на активний стек у порядку (таким чином, щоб останній вхід був над стеком).

Єдині дійсні символи в програмі Brain-Flak є ()[]{}<>, і вони завжди повинні бути врівноваженими . Якщо є недійсні символи або дужки є невідповідними, ви отримуєте не визначену поведінку. Все дійсне.

Є два типи функцій: Nilads і монади . Nilad це функція , яка приймає 0 аргументів. Ось усі нилади:

  • () +1.
  • [] -1.
  • {} Поп активного стека.
  • <> Увімкніть активний стек.

Вони об'єднуються разом, коли вони оцінюються. Отже, якщо у нас був "3" на верхній частині активного стека, цей фрагмент:

()(){}

оцінив би, до 1 + 1 + active.pop()чого оцінив би до 5. <>оцінює до 0.

Монади беруть один аргумент, шматок коду Брейн-Флак. Ось усі монади:

  • (n) Натисніть «n» на активний стек.
  • [n] Роздрукуйте 'n' як int та новий рядок.
  • {foo}Поки active.peek ()! = 0, виконайте foo. Оцінюється до 0¹.
  • <foo> Виконайте foo, але оцініть його як 0.

Ці функції також повернуть значення всередині них, так

(()()())

Буде натискати 3 і

[()()()]

Буде надруковано 3, але

[(()()())]

Надрукує та натисне 3.

Коли програма виконана, кожне значення, залишене на активному стеку, друкується як ціле число, з новим рядком між ними. Значення в іншій стеці ігноруються.

Правила:

  • Ваша програма повинна підтримувати номери в діапазоні (-128, 127) і розмір стека не менше 255. Якщо ви підтримуєте більше, чудово.

  • Підвищення / перелив не визначено.

Зразок IO:

Порожня програма:

Введення: Ні

Вихід: Немає

Доповнення. Джерело:

({}{})

Вхід:

2, 3

Вихід:

5

Віднімання. Джерело:

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

Вхід:

2, 3

Вихід:

-1

Множення. Джерело:

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

Вхід:

7, 8

Вихід:

56

Фібоначчі. Джерело:

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

Вхід:

5

Вихід:

13
8
5
3
2
1
1

Істина машина

{[({})]}

Застосовуються стандартні лазівки, і найкоротша відповідь у байтах виграє.


  • ¹: Це фактично була помилка з мого боку. {...} слід оцінити до суми всіх його запусків, що є ІМО однією з найкрутіших особливостей мозку. Однак для цілей цього виклику припустимо, що він {...} оцінюється як 0.

Чи існує правило щодо мінімального цілого значення, яке має працювати програма?
0 '

Що {...}оцінює монада ?
Ніл

У якому порядку розміщуються аргументи віднімання? Я отримую заперечення того, що очікую.
Ніл

@Neil Вибачте за це. Монада {...}оцінюється до 0. Також аргументи висуваються по порядку, тому 2натискається, потім 3висувається, тож коли програма запускається, другий вхід ( 3) знаходиться на вершині стека. Я уточню обох тих, хто на посаді.
DJMcMayhem

Відповіді:


6

Піп -n , 151 148 101 98 байт

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

Переглядає список входів як аргументи командного рядка та код Brain-Flak з (рядка) stdin. Спробуйте в Інтернеті!

Редагувати: Збережено чимало байтів над моїм оригінальним підходом, перейшовши на стратегію перекладу і переходу.

Негольфірованний і прокоментував

Ця версія також включає деякий вихід налагодження, що показує код Pip, який є результатом перекладу, а також вміст стеку після виконання.

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

Чи піп новий, ніж цей виклик?
DJMcMayhem

@DJMcMayhem Nope ! Я також не використовую будь-які функції, новіші, ніж виклик.
DLosc

59

Brain-Flak Classic , 1271 1247 1239 байт

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

Спробуйте в Інтернеті!

+4 байти від виправлення помилки з умовою в {...} монаді, і -36 байт від різних гольфів.

1238 байт коду, +1 байт для -a прапора (який можна поєднувати з мовним прапором).

Це зараз оцінює {...} як нуль за специфікацією виклику. Зауважимо, що Brain-Flak оцінив {...}як суму всіх запусків з виправлення 7 травня 2016 року за два дні до опублікування цього виклику.

Наступний код правильно інтерпретує Brain-Flak Classic із {...}сумою всіх прогонів. Єдина відмінність між двома перекладачами - це розміщення одного {}ниладу.

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

Спробуйте в Інтернеті!

Введення (для будь-якого інтерпретатора) - це програма Brain-Flak Classic для інтерпретації, потім новий рядок, а потім розділений пробілом список цілих чисел. Не здійснюється перевірка на вході. Новий рядок необхідний, навіть якщо програма або введення пусті.

Перший крок - проаналізувати весь вхід, починаючи з дужок:

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

Потім цілі числа розбираються. Зазвичай це не потрібно, але вхід приймається як ASCII. Однак у нього є срібляста підкладка: введення тексту дозволяє нам визначити висоту стека, що спрощує речі, коли ми не маємо доступу до висоти стека.

Цілі числа розбиваються на два числа на другому стеку: одне для абсолютного значення та одне для знака. Потім вони переміщуються назад до першого стеку.

Інтерпретовані стеки зберігаються під кодом на першому стеку в такому порядку: поточна висота стека, поточний стек, інша висота стека, інший стек. 0 для іншої висоти стека не потрібно натискати в цій точці, оскільки це буде неявний нуль при першому читанні.

(<((

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

Представлення коду тепер переміщено назад у лівий стек. Щоб полегшити ситуацію пізніше, ми віднімаємо 4 з відкриваючих дужок ніладів, так що кожна операція має унікальне ціле число від -1 до -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
    <>)

<>}<>{}

Основна частина програми - власне інтерпретація інструкцій. На початку кожної ітерації основного циклу поточна інструкція знаходиться у верхній частині лівої стеки, усе після неї знаходиться під цим же стеком, і все до того, як вона знаходиться в правій стеці. Я схильний уявляти це як відкриття книги на певній сторінці.

{

    (

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

    }{}

}

Після виходу з основного циклу весь код знаходиться у правій стеці. Єдині речі, що знаходяться в лівій стеці, - це нуль і дві інтерпретовані стеки. Отримати правильний вихід - справа проста.

# Pop the zero
{}

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

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

12
: О, що ... Добре, негайно збиваючись. Хороша робота! : D
DJMcMayhem

4
Дозвольте мені зрозуміти це ... ви створили перекладача для мови, яку слід інтерпретувати. YoDawg
tisaconundrum

Гаразд, чому він має лише двозначний номер оновлення?
NieDzejkob

Хороша робота над правильним впровадженням акумулятора {...}, що є правильною поведінкою для сучасної класичної мізки та (я думаю) класичного мозку, але я писав у виклику, який {...}оцінюється як 0. Ви, мабуть, могли б зіграти значну кількість байтів видаливши цю функціональність, хоча було б непогано тримати оригінал, оскільки це технічно правильніше взагалі (якраз неправильно для цього виклику)
DJMcMayhem

Виправлено @DJMcMayhem Просто не змушуйте мене перекладати весь перекладач до тієї гіпотетичної версії Мозга-Флака.
Nitrodon

8

APL, 255 257 байт

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

Це сприймає програму як її правильний аргумент, а програму - як лівий аргумент, тобто:

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

Негольована версія: тут .


7

APL (Dyalog Classic) , 146 байт

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

Спробуйте в Інтернеті!

одна класична інтерпретація іншої :)


6

Python 3, 429 байт

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

Використовується як g('[{}{}]', 2, 3)

Він використовує re.subдля "компіляції" джерела спалаху мозку для python, а потім виконує пітон. (для налагодження замініть execнаprint щоб отримати список пітонного коду)

Правильне відступ вкладених під час циклів з'їдає багато байтів у коді.


3

Пітон, 616 байт

Інструкції:

  1. Бігайте з пітоном
  2. Введіть список у [1,2,...]форматі, а потім натисніть клавішу Enter
  3. Вставити / записати програму, а потім знову натиснути клавішу Enter
  4. Зроблено

В основному, ця програма робить рекурсивно "компілювати" код Brain-flak в вкладені списки і рекурсивно інтерпретувати цей список. Напевно, є спосіб поєднати два ...

Я спробую переробити логіку пізніше.

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 байт

Я трохи гольфував, але, мабуть, є можливість вдосконалитись. Тут додано нові рядки та вкладки задля трохи читабельності:

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 байт

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

Спробуйте в Інтернеті!

-13 байт збережено завдяки @Mr. Xcoder!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.