Python 2, 157 octets
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
Ça a toujours l'air assez golfable, mais je poste ceci pour le moment. Il utilise la récursivité avec un peu de cache. De manière ennuyeuse, D.get
ne court-circuite pas pour la mise en cache, je ne peux donc pas économiser 9 octets de cette façon ...
Le mappage donne la priorité à la longueur, puis à l'ordre lexicographique par rapport à l'ordre "][><.-,+"
(voir les exemples de sortie ci-dessous). L'idée principale est de comparer les préfixes.
La variable o
garde trace du nombre de [
crochets encore ouverts pour le préfixe actuel, tandis que la variable d
prend l'une des trois valeurs suivantes:
d = 1
: Le préfixe actuel est lexicographiquement antérieur à s
. Ajoutez tous les programmes avec ce préfixe et cette longueur <= s
,
d = -1
: Le préfixe actuel est lexicographiquement plus tard que s
. Ajoutez tous les programmes avec ce préfixe et cette longueur < s
.
d = 0
: Le préfixe actuel est un préfixe de s
, nous pourrions donc passer d
à 1 ou -1 plus tard.
Par exemple, si nous avons s = "[-]"
et que notre préfixe actuel est p = "+"
, puisqu’il p
est plus tard que s
lexicographe, nous ne savons ajouter que les programmes commençant par p
qui sont strictement plus courts que s
.
Pour donner un exemple plus détaillé, supposons que nous ayons un programme d’entrée s = "-[]"
. La première expansion récursive fait ceci:
(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) # '+'
Notez que nous ne pas utiliser réellement les préfixes dans la récursivité - tout ce que nous soucions d'eux est capturé par les variables d
, o
et le programme d'entrée diminue s
. Vous remarquerez beaucoup de répétitions ci-dessus - c’est là que la mise en cache intervient, nous permettant de traiter les programmes de 100 caractères dans les délais impartis.
Quand s
est vide, nous regardons (d>=0 and o==0)
, qui décide s'il faut retourner 1 (compter ce programme parce que c'est lexicographiquement précoce / égal et que le programme est valide), ou 0 (ne pas compter ce programme).
Toute situtation avec o < 0
retour immédiat 0
, car tous les programmes avec ce préfixe ont plus de ]
s que [
, et sont donc invalides.
Les 20 premières sorties sont:
1
> 2
< 3
. 4
- 5
, 6
+ 7
[] 8
>> 9
>< 10
>. 11
>- 12
>, 13
>+ 14
<> 15
<< 16
<. 17
<- 18
<, 19
<+ 20
En utilisant le même exemple Hello World que la réponse de @ TheNumberOne:
>>> f("++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.")
3465145076881283052460228065290888888678172704871007535700516169748342312215139431629577335423L