J'ai pensé profiter de cette opportunité pour montrer une nouvelle fonctionnalité Retina: les boucles multi-étapes. Cela devrait considérablement raccourcir de nombreuses tâches (notamment le remplacement conditionnel).
ii
-
+`(.)\1|0
(.)-|(\d)(\d)
-$1$3$2
12
i3
23
i1
31
i2
)`(\d)i
i$1
^\D*$
$&0
Retina est mon propre langage de programmation basé sur l'expression rationnelle. Le code source peut être regroupé en étapes: chaque étape se compose de deux lignes où la première contient l'expression régulière (et éventuellement une configuration) et la deuxième ligne est la chaîne de remplacement. Les étapes sont ensuite appliquées à STDIN dans l'ordre et le résultat final est imprimé à STDOUT.
Vous pouvez utiliser ce qui précède directement comme fichier source avec le -s
commutateur de ligne de commande. Cependant, je ne compte pas le commutateur, car vous pouvez également simplement mettre chaque ligne dans un fichier séparé (vous perdez alors 15 octets pour les sauts de ligne, mais ajoutez +15 pour les fichiers supplémentaires).
Explication
La nouveauté de cette solution est )
l'avant-dernière étape. Cela ferme une boucle en plusieurs étapes. Il n'y a pas de correspondance (
, ce qui signifie que la boucle démarre implicitement au premier stade. Par conséquent, les 7 premières étapes sont répétées jusqu'à ce qu'un passage complet à travers les 7 étapes cesse de changer le résultat. Ces 7 étapes effectuent simplement diverses transformations qui réduisent progressivement le nombre de matrices dans la chaîne et combinent les phases. Une fois que nous atteignons le résultat final, aucun des sept modèles ne correspond plus et la boucle se termine. Ensuite, nous ajoutons un 0 s'il n'y a pas encore de chiffre dans le résultat (car les étapes ci-dessus suppriment simplement toutes les identités, y compris le résultat).
Voici ce que font les différentes étapes:
ii
-
Combine toutes les paires de i
en -
pour réduire les caractères de phase.
+`(.)\1|0
<empty>
Maintenant, s'il reste deux caractères identiques consécutifs, c'est soit --
deux matrices identiques. Dans les deux cas, leur multiplication donne l'identité. Mais nous n'avons pas besoin d'identités, nous les supprimons donc toutes, ainsi que les identités explicites 0
. Cette étape se répète en elle-même +
jusqu'à ce que le résultat cesse de changer. Cela garantit que des choses comme la 123321
résolution complète, de sorte que l'étape suivante peut supposer que toutes les paires de chiffres sont distinctes.
(.)-|(\d)(\d)
-$1$3$2
Il s'agit en fait de deux transformations distinctes en une (pour la golfitude). Notez que si la première alternative correspond, $2
et $3
sont vides, et si la seconde correspond $1
est vide. Cela peut donc être décomposé en ces deux étapes:
(\d)(\d)
-$2$1
Cela permute simplement toutes les paires de chiffres et ajoute un signe moins. Depuis que nous avons supprimé toutes les 0
s et toutes les paires identiques, cela ne correspond 12
, 23
, 31
, 21
, 32
, 13
. Cette étape peut sembler étrange, mais elle me permet de ne vérifier que la moitié de ces cas plus tard, car ceux que je ne peux pas traiter seront échangés ici lors de la prochaine itération.
L'autre partie de l'étape ci-dessus était:
(.)-
-$1
Cela déplace progressivement les -
panneaux vers la gauche (une position par itération). Je fais cela de telle sorte qu'en fin de compte, ils sont tous côte à côte et résolus à l'étape précédente.
12
i3
23
i1
31
i2
Ces trois étapes résolvent désormais simplement les trois paires de produits. Comme je l'ai dit ci-dessus, cela n'attrapera que la moitié des cas pertinents, mais l'autre moitié sera prise en charge lors de la prochaine itération, après que l'étape précédente ait échangé toutes les paires.
)`(\d)i
i$1
C'est la dernière étape de la boucle. Il est similaire à celui qui se déplace -
vers la gauche, à l'exception de i
. La principale différence est que celui-ci échange i
uniquement avec des chiffres. Si j'utilisais (.)i
alors dans les cas où j'obtiens un -i
ou i-
les deux seraient échangés indéfiniment et le programme ne se terminerait pas. Cela ne fait donc que les échanger à droite des -
panneaux. C'est suffisant - tant que tous -
et i
apparaissent ensemble à un moment donné, ils peuvent être résolus correctement.
^\D*$
$&0
La dernière étape (en dehors de la boucle). N'oubliez pas que nous avons toujours supprimé toutes les identités, donc si le résultat est réellement l'identité (fois une phase), nous n'aurons plus le chiffre requis dans la sortie, nous l'ajoutons donc.
À titre d'exemple, voici toutes les formes intermédiaires de 0223202330203313021301011023230323
(saut d'étapes qui n'effectuent aucun changement):
0223202330203313021301011023230323
321321312 # Remove identities
-23-31-12-132 # Swap all pairs
-23-31-i3-132 # Resolve 12
-i1-31-i3-132 # Resolve 23
-i1-i2-i3-132 # Resolve 31
-i-1i-2i-3-312 # Move - to the left and swap pairs
-i-1i-2i-3-3i3 # Resolve 12
-i-i1-i2-3-i33 # Move i to the left
-i-i1-i2-3-i # Remove identities
--ii-1i-2-3i # Move - to the left
--ii-i1-2-i3 # Move i to the left
----i1-2-i3 # Resolve ii
i1-2-i3 # Remove identities
i-1-2i3 # Move - to the left
i-1-i23 # Move i to the left
-i-1i-32 # Move - to the left and swap pairs
-i-i1-32 # Move i to the left
--ii-1-23 # Move - to the left and swap pairs
--ii-1-i1 # Resolve 23
----1-i1 # Resolve ii
1-i1 # Remove identities
-1i1 # Move - to the left
-i11 # Move i to the left
-i # Remove identities. Now the loop can't change this any longer.
-i0 # Fix the result by adding in the 0.