写一个脑力激荡的经典口译员!


18

Brain-Flak(Brainf ** k和Flak-Overstow之间的交叉)是一种基于堆栈的深奥语言。自发布此挑战以来,该语言已得到发展和更新,但是该语言的第一个修订版被称为“经典大脑”。

您必须编写一个程序或函数,该程序或函数需要一串Brain-Flak经典代码并对其进行评估。它还将使用(可能为空)整数列表。有Brain-Flak经典程序的输入。

语言

Brain-Flak具有两个堆栈,分别称为“左”和“右”。活动堆栈从左侧开始。如果弹出或查看一个空堆栈,它将返回0。没有变量。程序启动时,每个输入将按顺序推入活动堆栈(以便最后一个输入位于堆栈顶部)。

Brain-Flak程序中唯一有效的字符是()[]{}<>,并且必须始终保持平衡。如果有无效字符,或者括号不匹配,则会出现不确定的行为。任何有效的东西。

函数有两种类型:NiladsMonads。一个nilad是一个函数,0参数。这是所有的尼拉德人:

  • () +1。
  • [] -1。
  • {} 弹出活动堆栈。
  • <> 切换活动堆栈。

在评估它们时将它们串联在一起。因此,如果我们在活动堆栈的顶部有一个“ 3”,则此代码段:

()(){}

将评估到1 + 1 + active.pop()将评估为5。将<>评估为0。

单子组采用一个参数,即一大堆Brain-Flak代码。这是所有单子:

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

真相机

{[({})]}

存在标准漏洞,最短的答案以字节为单位。


  • ¹:这实际上是我的错误。 {...} 应该对所有运行的总和进行评估,这是IMO最有效的功能之一。但是,出于此挑战的目的,假定其 {...} 值为0。

是否存在有关程序需要处理的最小整数值的规则?
0'

单子{...}评估什么?
尼尔

减法参数按什么顺序排列?我正在得到我所期望的否定。
尼尔

@尼尔很抱歉。monad的{...}计算结果为0。此外,参数按顺序2推入,先3推入,然后推入,因此在程序启动时,第二个输入(3)在堆栈顶部。我将在帖子中澄清这两个问题。
DJMcMayhem

Answers:


6

PIP -n151个 148 101 98字节

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

将输入列表作为命令行参数以及来自stdin(一行)的Brain-Flak代码。在线尝试!

编辑:通过转换为转换和评估策略,在我的原始方法上节省了很多字节。

取消评论

此版本还包括一些调试输出,这些输出显示转换产生的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 都能跟得上!我也没有使用比挑战更新的功能。
DLosc

59

Brain-Flak Classic1271 1247 1239字节

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

在线尝试!

+4个{...}字节可修复具有monad 条件的错误,而+36个字节来自各种高尔夫球。

1238个字节的代码,-a标志+1个字节(可以与语言标志结合使用)。

现在{...},根据挑战说明,其评估为零。请注意,{...}自发布此挑战前两天,自2016年5月7日错误修正以来,Brain-Flak本身已将所有运行的总和进行评估。

以下代码正确地解释了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。不过,这确实有一线希望:文本输入使我们能够确定堆栈高度,当我们无法访问堆栈高度nilad时,这可以简化事情。

整数在第二个堆栈上被解析为两个数字:一个用于绝对值,另一个用于符号。然后将这些移回第一堆栈。

解释后的堆栈按以下顺序存储在第一个堆栈上的代码下方:当前堆栈高度,当前堆栈,其他堆栈高度,其他堆栈。此时不需要将其他堆栈高度的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
>)

代码的表示现在移回到左侧堆栈。为了使事情变得更简单,我们从nilads的左括号中减去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
:O什么...好吧,立即悬赏。不错的工作!:D
DJMcMayhem

4
让我直接讲...您为要解释的语言创建了一个解释器。YoDawg
tisaconundrum

好的,为什么只有2位数的投票编号?
NieDzejkob

在正确实现累加器方面做得不错{...},这是现代脑筋急转弯和(我认为)脑筋急转弯经典动作的正确行为,但是我在挑战中写道,该{...}求值为0。通过删除该功能,尽管保留原始版本会很不错,因为从技术上来说,它通常更正确(对于此挑战来说是错误的)
DJMcMayhem

@DJMcMayhem固定。只是不要让我将整个解释器移植到那个虚构的Brain-Flak版本。
Nitrodon '17

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将“大脑Flak”源“编译”为python,然后执行python。(用于调试,请替换execprint以获得python代码列表)

适当缩进嵌套的while循环会占用代码中的很多字节。


3

Python,616字节

说明:

  1. 使用python运行
  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

在线尝试!

@Mr节省了-13个字节。Xcoder!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.