这个问题是旨在庆祝Brain-Flak的第一个生日的几个Brain-flak Birthday挑战中的第一个!您可以在此处找到有关Brain-Flak诞辰的更多信息
去年夏天,我们有了Brain-flak Integer Metagolf,此后产生的答案对Brain-Flak社区非常有用。使Integer Metagolf如此高效的主要因素是一种称为乘法硬编码的技术。
在Brain-Flak中,运行时乘法非常昂贵。已知的最短乘法片段为:
({}<>)({<({}[()])><>({})<>}{}<><{}>)
被Megatom发现
但是,有一种非常简单的方法来创建编译时间乘法。例如,以下代码将乘以5:
(({})({})({})({}){})
这是有效的,因为连续的表达式被添加在一起。每个({})
都对堆栈不执行任何操作(将其{}
弹出并(..)
向右推),并求值到堆栈顶部的任何内容。所有这些表达式加起来等于堆栈顶部的五倍。
对于n
以下任何字符串表达式,将创建一个片段,该片段会将堆栈顶部乘以n
:
"("+"({})"*(n-1)+"{})"
这是通过制作n
所有表达式都计算到堆栈顶部的表达式来实现的。第一个n-1
实际上不更改任何内容,最后一个在推送之前删除堆栈的顶部。
对于复合数字,您可以将多个较小的表达式链接在一起以节省字节。例如,您可以乘以5两次来乘以25:
(({})({})({})({}){})(({})({})({})({}){})
这很简单,对于某些数字来说,它工作得很好,但是有更好的方法可以做到这一点。例如,我想出的一种方法使用数字的二进制表示形式。(这是一个python实现)这种新方法比前面显示的简单字符串表达式要有效得多,但它还没有结束,有各种各样有趣的方式来对乘法进行硬编码,而且可能还没有发现。
所以我认为现在是时候看看我们能取得多好的成就。
大脑爆发概述
这是您对此挑战需要了解的所有信息的描述。
Brain-Flak有“ nilads”和“ monads”。Nilads是括号,里面没有任何内容。每个尼拉德人都会做一件事情,并返回一个值。对于这一挑战,我们关注的两个尼拉德是{}
和<>
。 {}
弹出活动堆栈的顶部并返回其值。<>
切换活动堆栈和活动堆栈,以便活动堆栈变为非活动状态,非活动堆栈变为活动状态,它返回零。
Monad是其中包含东西的括号。他们接受一个参数,即它们内部所有内容的总和,有时执行一个动作,然后返回一个值。我们关心的是,这些三是(...)
,<...>
和[...]
。对于此挑战,最重要的单子(...)
取整内部的值并将其推入活动堆栈。然后,它返回参数。 <...>
并且[...]
都是“惰性”单子,即它们不执行任何操作,而是修改它们传递的值。 <...>
无论传递的参数如何,总是返回零。同时[...]
总是返回参数次数-1
。
带有解释的示例程序
如果您从未使用Brain-Flak编程,那么最好使用描述的操作来查看一些示例程序。
({}{})
这会将堆栈中的前两个数字相加。每个都{}
从堆栈中弹出一个值,然后(...)
将其和推回。
({}[{}])
同样,这将从堆栈中减去堆栈中的第二个项目。就像之前每个都{}
弹出一个值一样,但是[..]
第二个值前后会导致它被添加。再次(...)
推动总和。
({}<{}>)
这将删除堆栈中的第二个值,并保持最高值不变。它的工作方式与最后两个一样,只不过第二个值被静音,<...>
因此推入仅将第一个值推回。
(({}))
这将在堆栈顶部复制第二个值。它通过弹出堆栈顶部并{}
获取其值来执行此操作,(..)
然后先将其推回其值求值。第二个(...)
取第一个返回的值,并将其推入堆栈。创建第二个副本。
任务
给定一个整数,n
创建一个堆栈干净的Brain-Flak代码段,该代码段将当前堆栈的顶部乘以n
。
您被允许使用以下Brain-Flak操作
(...) -> Push Monad, Pushes the result of its contents
<...> -> Zero Monad, Returns zero
[...] -> Negative Monad, Returns the opposite of its contents result
{} -> Pop nilad, Pops the TOS and returns its value
<> -> Switch nilad, Switches the active and inactive stack
出于挑战的目的,其他操作被禁止。
计分
您的分数将是从n=2
到的所有程序的累积长度n=10000
。确保包含指向程序输出的链接以进行验证。
[...]
,这是一个开始。