Python 2,157字节
def f(s,o=0,d=0,D={}):T=s,o,d;x=D[T]=D[T]if T in D else~o and 0**o+sum(f(s[1:],cmp(c,"[")%-3-~o,d or cmp(c,s[0]))for c in"+,-.<>[]")if s else~d<0==o;return+x
看起来仍然很适合打高尔夫球,但我现在将其发布。它使用递归和一些缓存。烦人的是,D.get
缓存不会短路,所以我不能那样保存9个字节...
映射优先顺序是长度,然后是字典顺序"][><.-,+"
(顺序如下)(请参见下面的输出示例)。主要思想是比较前缀。
该变量o
跟踪[
针对当前前缀仍处于打开状态的括号的数量,而该变量d
采用表示以下内容的三个值之一:
d = 1
:当前的前缀在字典上早于s
。添加所有具有此前缀和长度的程序<= s
,
d = -1
:当前前缀在字典上晚于s
。添加所有具有此前缀和长度的程序< s
。
d = 0
:当前前缀是的前缀s
,因此以后我们可能会更改d
为1或-1。
例如,如果我们有s = "[-]"
并且我们的当前前缀是p = "+"
,因为p
它比s
字典上晚,我们只知道添加p
严格比开头的程序s
。
为了给出更详细的示例,假设我们有一个输入程序s = "-[]"
。第一个递归扩展执行此操作:
(o == 0) # Adds a program shorter than s if it's valid
# For the first expansion, this is 1 for the empty program
+ f(s[1:], o=-1, d=1) # ']', o goes down by one due to closing bracket
+ f(s[1:], o=1, d=1) # '[', o goes up by one due to opening bracket
+ f(s[1:], o=0, d=1) # '>'
+ f(s[1:], o=0, d=1) # '<'
+ f(s[1:], o=0, d=1) # '.', d is set to 1 for this and the previous branches
# since they are lexicographically earlier than s's first char
+ f(s[1:], o=0, d=0) # '-', d is still 0 since this is equal to s's first char
+ f(s[1:], o=0, d=-1) # ',', d is set to -1 for this and the later branches
# since they are lexicographically later than s's first char
+ f(s[1:], o=0, d=-1) # '+'
注意我们如何不实际使用前缀的递归-我们关心他们是通过变量捕获d
,o
而且收缩输入程序s
。您会在上面注意到很多重复-这是缓存的来源,这使我们能够在规定的时间内很好地处理100个字符的程序。
当s
为空时,我们查看(d>=0 and o==0)
,它决定是返回1(对程序进行计数,因为它在字典上早/等于,并且程序有效),还是返回0(不对程序进行计数)。
与任何situtation o < 0
立即返回0
,因为以这个前缀任何程序有更多的]
除S [
,并因此无效。
前20个输出是:
1
> 2
< 3
. 4
- 5
, 6
+ 7
[] 8
>> 9
>< 10
>. 11
>- 12
>, 13
>+ 14
<> 15
<< 16
<. 17
<- 18
<, 19
<+ 20
使用与@TheNumberOne的答案相同的Hello World示例:
>>> f("++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.")
3465145076881283052460228065290888888678172704871007535700516169748342312215139431629577335423L