Python 2, 157 byte
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
Sembra ancora abbastanza giocabile, ma sto pubblicando questo per ora. Usa la ricorsione con un po 'di cache. In modo fastidioso, D.get
non corto circuito per la memorizzazione nella cache, quindi non posso salvare 9 byte in questo modo ...
La mappatura privilegia prima la lunghezza, quindi l'ordine lessicografico rispetto all'ordinamento "][><.-,+"
(vedere gli esempi di output di seguito). L'idea principale è quella di confrontare i prefissi.
La variabile o
tiene traccia del numero di [
parentesi ancora aperte per il prefisso corrente, mentre la variabile d
accetta uno dei tre valori che indicano:
d = 1
: Il prefisso attuale è lessicograficamente precedente a s
. Aggiungi tutti i programmi con questo prefisso e lunghezza <= s
,
d = -1
: Il prefisso attuale è lessicograficamente più tardi di s
. Aggiungi tutti i programmi con questo prefisso e lunghezza < s
.
d = 0
: Il prefisso corrente è un prefisso di s
, quindi potremmo cambiare d
in 1 o -1 in seguito.
Ad esempio, se abbiamo s = "[-]"
e il nostro prefisso attuale è p = "+"
, poiché p
è più tardi che s
lessicograficamente sappiamo solo di aggiungere i programmi che iniziano con i p
quali sono strettamente più brevi di s
.
Per fare un esempio più dettagliato, supponiamo di avere un programma di input s = "-[]"
. La prima espansione ricorsiva fa questo:
(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) # '+'
Si noti come in realtà non utilizzare i prefissi nella ricorsione - tutti ci preoccupiamo per loro viene catturato attraverso le variabili d
, o
e il programma di input contrazione s
. Noterai molte ripetizioni sopra: è qui che entra in gioco la cache, che ci consente di elaborare programmi da 100 caratteri entro il limite di tempo.
Quando s
è vuoto, guardiamo (d>=0 and o==0)
, che decide se restituire 1 (conta questo programma perché è lessicograficamente in anticipo / uguale e il programma è valido), o 0 (non contare questo programma).
Qualsiasi situtazione con o < 0
ritorna immediatamente 0
, poiché tutti i programmi con questo prefisso hanno più ]
s di [
, e quindi non sono validi.
Le prime 20 uscite sono:
1
> 2
< 3
. 4
- 5
, 6
+ 7
[] 8
>> 9
>< 10
>. 11
>- 12
>, 13
>+ 14
<> 15
<< 16
<. 17
<- 18
<, 19
<+ 20
Utilizzando lo stesso esempio Hello World della risposta di @ TheNumberOne:
>>> f("++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.")
3465145076881283052460228065290888888678172704871007535700516169748342312215139431629577335423L