<>(()){<>((([][][][][])<(((({}){})(({})({}))[])({}(({})({}({})({}{}(<>)))))[])>{()<{}>}{})<{{}}{}>())}{}<>(<(({()(((<>))<>)}{}{<({}(([][][])((({})({}))[]{})){})>((){[]<({}{})((){[]<({}{}<>((({})({})){}{}){})(<>)>}{}){{}{}<>(<({}{}())>)(<>)}>}{}){(<{}{}{}((<>))<>>)}{}}<>)<{({}[]<({}<>)<>{(<{}>)<>{<>({}[])}{}<>({}<>)(<>)}{}>)}{}<>>)>)<>{(({}[])(){(<{}>)<><(({})[])>[][][][]{()()()()(<{}>)}{}<>}{}<>)<>}<>{}{(({})<({()<<>({}<>)>}{})>([]))((){[](<(({}()()(<>))()()()){(<{}>)<>}>)}{}<>){{}((){[]<({}())((){[]<({}())((){[]<({}())((){[]<({}())((){[]<({}())((){[]<({}())((){[](<{}<>{({}<>)<>}{}(({}))({<{}({}<>)<>>{}(<<>({}[]<>)>)}<><{({}<>)<>}>{})>)}{}){{}{}(<([])>)}>}{}){{}<>{({}<>)<>}{}((({})())<{({}[]<({}<>)<>>)}>{}){({}[]<><({}<><({()<({}[]<({}<>)<>>)>}{}<>)><>)<>({()<({}[]<({}<>)<>>)>}{}<>)>)}<>(<{({}<>)<>}>)}>}{}){{}{}(<(())>)}>}{}){(<{}{}>)<>{({}<>)<>}{}(({}))({<{}({}<>)<>>({})(<<>({}<>)>)}<><{({}<>)<>}>){{}([][][])<>(((<{}>)<>))}}>}{}){{}(<([{}])>)}>}{}){{}((<{}>))}>}{}){{}(({})(<()>)<<>{({}<>)<>}{}({}()<>)<>>)<>(<({}<>)>)<>{({}<>)<>}}{}(<({}<({}<>)<>>{})<>({}<>)>)<>(<({}())>)}{}({}<{({}[]<({}<>)<>>)}{}>){((({}[]<>){(<{}({}<>)>)}{}())<{({}()<({}<>)<>(({})[])>{[][](<{}>)}{})}{}>()){{}(<>)}}{}}{}{({}[]<[{}]>)}{}{({}[]<{}>)}{}
在线尝试!
+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
{({}[]<{}>)}{}