Hexagony , 920 722 271 octets
Six types de boucles de fruits, vous dites? C'est pour cela que Hexagony a été conçu .
){r''o{{y\p''b{{g''<.{</"&~"&~"&<_.>/{.\.....~..&.>}<.._...=.>\<=..}.|>'%<}|\.._\..>....\.}.><.|\{{*<.>,<.>/.\}/.>...\'/../==.|....|./".<_>){{<\....._>\'=.|.....>{>)<._\....<..\..=.._/}\~><.|.....>e''\.<.}\{{\|./<../e;*\.@=_.~><.>{}<><;.(~.__..>\._..>'"n{{<>{<...="<.>../
Ok, ça ne l'était pas. Oh mon Dieu, qu'est-ce que je me suis fait ...
Ce code est maintenant un hexagone de côté 10 (il a commencé à 19). Cela pourrait probablement être joué un peu plus, peut-être même à la taille 9, mais je pense que mon travail est fait ici ... Pour référence, il y a 175 commandes réelles dans la source, dont beaucoup sont des miroirs potentiellement inutiles (ou ont été ajoutées pour annuler une commande depuis un passage à niveau).
Malgré l'apparente linéarité, le code est en fait à deux dimensions: Hexagony le réorganisera en un hexagone normal (qui est également un code valide, mais tous les espaces sont facultatifs dans Hexagony). Voici le code non plié dans tous ses aspects ... eh bien, je ne veux pas dire "beauté":
) { r ' ' o { { y \
p ' ' b { { g ' ' < .
{ < / " & ~ " & ~ " & <
_ . > / { . \ . . . . . ~
. . & . > } < . . _ . . . =
. > \ < = . . } . | > ' % < }
| \ . . _ \ . . > . . . . \ . }
. > < . | \ { { * < . > , < . > /
. \ } / . > . . . \ ' / . . / = = .
| . . . . | . / " . < _ > ) { { < \ .
. . . . _ > \ ' = . | . . . . . > {
> ) < . _ \ . . . . < . . \ . . =
. . _ / } \ ~ > < . | . . . . .
> e ' ' \ . < . } \ { { \ | .
/ < . . / e ; * \ . @ = _ .
~ > < . > { } < > < ; . (
~ . _ _ . . > \ . _ . .
> ' " n { { < > { < .
. . = " < . > . . /
Explication
Je n'essaierai même pas de commencer à expliquer tous les chemins d'exécution compliqués de cette version golfée, mais l'algorithme et le flux de contrôle global sont identiques à cette version non golfée, qui pourrait être plus facile à étudier pour les plus curieux après avoir expliqué l'algorithme:
) { r ' ' o { { \ / ' ' p { . . .
. . . . . . . . y . b . . . . . . .
. . . . . . . . ' . . { . . . . . . .
. . . . . . . . \ ' g { / . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . > . . . . < . . . . . . . . .
. . . . . . . . . . . . . . > . . ) < . . . . .
. . . . . . . . . . / = { { < . . . . ( . . . . .
. . . . . . . . . . . ; . . . > . . . . . . . . . <
. . . . . . . . . . . . > < . / e ; * \ . . . . . . .
. . . . . . . . . . . . @ . } . > { } < . . | . . . . .
. . . . . / } \ . . . . . . . > < . . . > { < . . . . . .
. . . . . . > < . . . . . . . . . . . . . . . | . . . . . .
. . . . . . . . _ . . > . . \ \ " ' / . . . . . . . . . . . .
. . . . . . \ { { \ . . . > < . . > . . . . \ . . . . . . . . .
. < . . . . . . . * . . . { . > { } n = { { < . . . / { . \ . . |
. > { { ) < . . ' . . . { . \ ' < . . . . . _ . . . > } < . . .
| . . . . > , < . . . e . . . . . . . . . . . . . = . . } . .
. . . . . . . > ' % < . . . . . . . . . . . . . & . . . | .
. . . . _ . . } . . > } } = ~ & " ~ & " ~ & " < . . . . .
. . . \ . . < . . . . . . . . . . . . . . . . } . . . .
. \ . . . . . . . . . . . . . . . . . . . . . . . < .
. . . . | . . . . . . . . . . . . . . . . . . = . .
. . . . . . \ . . . . . . . . . . . . . . . . / .
. . . . . . > . . . . . . . . . . . . . . . . <
. . . . . . . . . . . . . . . . . . . . . . .
_ . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
Honnêtement, dans le premier paragraphe, je ne plaisantais qu'à moitié. Le fait que nous ayons affaire à un cycle de six éléments était en fait une aide précieuse. Le modèle de mémoire de Hexagony est une grille hexagonale infinie où chaque bord de la grille contient un entier signé à précision arbitraire, initialisé à zéro.
Voici un schéma de la disposition de la mémoire que j'ai utilisée dans ce programme:
Le long bit droit à gauche est utilisé comme une chaîne a
de taille arbitraire terminée par 0 qui est associée à la lettre r . Les lignes pointillées sur les autres lettres représentent le même type de structure, chacune pivotée de 60 degrés. Initialement, le pointeur de la mémoire pointe vers le bord étiqueté 1 , face au nord.
Le premier bit linéaire du code définit "l'étoile" intérieure des arêtes sur les lettres roygbp
et définit l'arête initiale sur 1
, de sorte que nous sachions où se termine / commence le cycle (entre p
et r
):
){r''o{{y''g{{b''p{
Après cela, nous sommes de retour sur le bord étiqueté 1 .
Maintenant, l’idée générale de l’algorithme est la suivante:
- Pour chaque lettre du cycle, continuez à lire les lettres de STDIN et, si elles sont différentes de la lettre actuelle, ajoutez-les à la chaîne associée à cette lettre.
- Lorsque nous lisons la lettre que nous recherchons actuellement, nous stockons un
e
libellé dans le bord ? , parce que tant que le cycle n’est pas terminé, nous devons supposer que nous devrons aussi manger ce personnage. Ensuite, nous nous déplacerons dans l'anneau jusqu'au prochain caractère du cycle.
- Ce processus peut être interrompu de deux manières:
- Soit nous avons terminé le cycle. Dans ce cas, nous faisons un autre tour rapide dans le cycle, en remplaçant tous ces
e
s dans le ? bords avec n
s, parce que maintenant nous voulons que ce cycle reste sur le collier. Ensuite, nous passons à l’impression de code.
- Ou nous frappons EOF (que nous reconnaissons comme un code de caractère négatif). Dans ce cas, nous écrivons une valeur négative dans le ? bord du caractère actuel (afin que nous puissions facilement le distinguer des deux
e
et n
). Ensuite, nous recherchons l’ arête 1 (pour ignorer le reste d’un cycle potentiellement incomplet) avant de passer également à l’impression de code.
- Le code d'impression répète le cycle: pour chaque caractère du cycle, il efface la chaîne enregistrée lors de l'impression d'un
e
pour chaque caractère. Ensuite, il passe à la ? bord associé au personnage. Si c'est négatif, nous terminons simplement le programme. Si c'est positif, nous l'imprimons simplement et passons au caractère suivant. Une fois le cycle terminé, nous revenons à l’étape 2.
Une autre chose qui pourrait être intéressante est la façon dont j'ai implémenté les chaînes de taille arbitraire (car c'est la première fois que j'utilise de la mémoire non limitée dans Hexagony).
Imaginez que nous sommes à un moment où nous sommes encore la lecture des caractères pour r (afin que nous puissions utiliser le schéma comme est) et un [0] et un 1 ont déjà été rempli de personnages (tout au nord-ouest d'entre eux est toujours zéro ) Par exemple, nous venons peut-être de lire les deux premiers caractères og
de l'entrée dans ces bords et nous lisons maintenant un y
.
Le nouveau caractère est lu dans le en bord. Nous utilisons le ? bord pour vérifier si ce caractère est égal à r
. (Il y a un truc astucieux ici: Hexagony ne peut faire la distinction que entre positif et non positif, donc vérifier l’égalité par soustraction est ennuyeux et nécessite au moins deux branches. Mais toutes les lettres sont moins qu’un facteur 2 les unes des autres, donc on peut comparer les valeurs en prenant le modulo, qui ne donnera zéro que si elles sont égales.)
Parce que y
est différent r
, on déplace le (non marqué) bord gauche de dans et copier le y
là. Nous allons maintenant plus loin dans l’hexagone, en copiant le caractère d’un bord à chaque fois, jusqu’à ce que nous ayons y
le bord opposé de dans . Mais maintenant, il y a déjà un caractère dans un [0] que nous ne voulons pas écraser. Au lieu de cela, nous "glissons" y
autour du prochain hexagone et vérifions un 1 . Mais il y a aussi un personnage là-bas, alors nous allons un autre hexagone plus loin. Maintenant, un [2] est toujours égal à zéro, nous copions donc ley
dans ça. Le pointeur de mémoire se déplace maintenant le long de la chaîne vers l'anneau intérieur. Nous savons quand nous avons atteint le début de la chaîne, car les arêtes (non étiquetées) entre les a [i] sont toutes égales à zéro alors que ? est positif.
Ce sera probablement une technique utile pour écrire du code non trivial dans Hexagony en général.