C'était étonnamment délicat, et je ne suis pas convaincu que ce soit optimal ...
<.@!$?
Après avoir rempli et déplié le code, cela représente la grille hexagonale suivante:
Cela utilise un flux de contrôle similaire à celui de mon récent programme de chat sans erreur , qui suit des anti-diagonales. Pour y parvenir, nous commençons par dévier le pointeur d’instruction (IP) vers la gauche, où le chemin violet s’enroule dans le coin inférieur gauche.
?
lit l'entrée sous forme d'entier. !
l'imprime en retour. .
est juste un no-op. Maintenant le coin de la grille agit comme une branche:
Si l'entrée était 0
, l'IP continuera le long du chemin rouge, qui termine simplement le programme avec @
.
Si l'entrée était 1
, l'IP continuera sur le chemin vert. Encore une fois, .
c'est juste un non-op, mais $
c'est l'équivalent du trampoline de Befunge: il saute l'instruction suivante. Après l’emballage, l’instruction suivante serait le ?
, mais en raison de l’ $
exécution, elle continue sur le chemin bleu, en commençant par !
imprimer une autre copie du fichier 1
. Cette boucle qui ne contient que !..$
se répète maintenant indéfiniment.
Une étude du flux de contrôle en hexagone ...
Je crois que la solution ci-dessus est optimale. J'ai écrit un test forcé brutal, qui vérifie tous les programmes Hexagony de 6 octets, qui en contiennent au moins un ?!@
(ce qui est nécessaire; j'ai également vérifié :
et %
au lieu de @
terminer avec une erreur de division par zéro, mais cela n'a pas aidé non plus). Le chèque imprime tous les programmes qui a) produisent une 0
entrée 0
et se terminent et b) produisent au moins deux 1
s (et rien d’autre) et ne se terminent pas dans les 60 premiers ticks du programme (200 ticks pour des solutions à 5 octets) . Je doute qu'une solution valable prenne plus de 200 ticks pour imprimer correctement la première 0
ou la seconde 1
sur une grille aussi petite. Je ne pense donc pas avoir manqué de solutions potentielles.
La recherche n'a donné aucun résultat pour 5 octets, mais 57 résultats pour 6 octets (en utilisant @
; il n'est pas nécessaire de terminer par une erreur si nous pouvons résoudre ce problème proprement dans le même nombre d'octets). Sur ces 57, seuls 6 étaient des faux positifs qui n’imprimaient en réalité que deux 1
secondes puis entraient dans une boucle infinie sans plus imprimer. Une solution a été répertoriée deux fois car elle contenait deux !
commandes. Cela laisse exactement 50 solutions valables.
Il existe une certaine dégénérescence entre les solutions où un ou deux caractères ne sont pas substantiels, par exemple parce qu’ils sont de toute façon sans exception. Les solutions peuvent être regroupées en 23 ensembles de programmes véritablement distincts (dans certains cas, il n’ya qu’une différence de caractère entre deux ensembles, mais cela modifie considérablement le flux de contrôle, je les ai donc comptés séparément). Deux des groupes utilisent même plusieurs indicateurs d'instruction de manière très inattendue. Comme je n’aurais jamais trouvé la plupart de ces façons d’utiliser les branches et les miroirs, elles constituent une étude très intéressante sur les types de flux de contrôle possibles dans Hexagony, et j’ai définitivement appris de nouvelles astuces pour les futurs golfs.
Le flux de contrôle global est presque toujours le même: lisez un nombre, imprimez-le. Si c'est le 0
moyen de trouver le @
, sinon continuez en boucle !
tout en conservant une valeur de bord de 1
. Il y a quatre exceptions notables:
- Une solution (celle avec deux
!
) imprime deux 1
s par itération dans la grille, soit environ deux fois plus vite que la majorité des programmes. J'ai marqué celui-ci avec x2
ci-dessous.
- Quelques solutions (celles qui contiennent un
o
) remplacent le 1
avec un 111
(le code de caractère de o
), de sorte qu’elles impriment trois 1
secondes par itération, leur permettant d’imprimer environ trois fois plus vite que la plupart des programmes. Je les ai marqués avec x3
ci-dessous.
- Deux solutions ajoutent un a
1
la valeur du bord à chaque itération (donc 1
-> 11
-> 111
-> ...). Ceux-ci impriment très vite, mais ils finiront par manquer de mémoire. Je les ai marqués avec OoM
ci-dessous.
- Deux solutions entrent dans une boucle très serrée qui ne fait que rebondir par-dessus l’
!
impression, imprimant tous les tics (au lieu de tous les 5 secondes environ), ce qui les rend légèrement plus rapides (et plus propres). Je les ai marqués avec ><
ci-dessous.
Alors voici le zoo entier:
#1 #5 #12 #19
?!/$.@ ?$!>$@ .?!/$@ |!|?$@ # ><
?!/$1@ # OoM ?$!|$@ =?!/$@
?!/$=@ #20
?!/$\@ #6 #13 $@.?<!
?!/$o@ # x3 ?/!<|@ .?/!$@ $@1?<! # OoM
?!/$!@ # x2 =?/!$@ $@=?<!
#7 $@o?<! # x3
#2 ?\!<|@ #14
?!>$)@ \!?__@ #21
?!>$1@ #8 _>_!?@
?!>$o@ # x3 ?<!>$@ # >< #15
?!|$)@ \_?!$@ #22
?!|$1@ #9 <!@.$?
?!|$o@ # x3 ?\$!@$ #16 <!@/$?
\_?!_@ <!@=$?
#3 #10 <$@!$?
?!|)$@ ?~#!@) #17 <.@!$?
?!|1$@ ?~#!@1 $$?\@! </@!$?
?!|o$@ # x3 <=@!$?
#11 #18
#4 ?$)\@! \$?\@! #23
?_!<@> ?$1\@! <<@]!?
?$o\@! # x3
Ce qui suit est une courte présentation de quelques groupes plus représentatifs. Les groupes 10 et 23 sont particulièrement intéressants. Il existe de nombreux autres chemins intéressants et parfois compliqués dans les autres groupes, mais je pense que je vous ai assez ennuyé à la fin. Pour ceux qui veulent vraiment apprendre l’hexagone, il convient néanmoins de s’y intéresser, car ils présentent un nombre encore plus grand d’utilisations possibles des miroirs et $
.
Groupe 1
Celui-ci n'est pas beaucoup plus élaboré que ma solution d'origine, mais les chemins vont dans des directions différentes. Il permet également le plus grand nombre de variations dans une seule cellule, car le no-op no-op le plus à droite peut être remplacé par 5 commandes différentes, ce qui permet de rendre cette opération valide sans modifier la structure:
Groupe 2
Celui-ci est très intéressant, car il ne se déplace que horizontalement. Après avoir enveloppé à la >
, l'IP inverse immédiatement, en prenant la branche dans le coin. Ce n'est pas tout à fait visiblement pas le diagramme, mais dans le cas de la 1
nous traversons à nouveau la première ligne, mais à l'envers cette fois. Cela signifie également que nous nous heurtons à ?
nouveau, ce qui nous revient maintenant 0
(EOF). Ceci est corrigé avec )
(incrément) pour continuer à imprimer 1
s. Cela a aussi 5 variations, comme cela )
pourrait aussi être 1
ou o
, et >
pourrait aussi être |
:
Groupe 3
Celui-ci semble presque identique au précédent, mais c'est désordonné. Jusqu'à frapper |
puis traverser la rangée du bas ou du haut, c'est la même chose. Mais dans le cas d'une boucle, le $
passe maintenant )
sur le miroir. Nous suivons donc le chemin turquoise à droite, maintenant frappé l'incrément, sauter par- dessus l' @
avant enrouler autour de la à |
nouveau et puis remontons sur le chemin vert en haut.
Groupe 4
Je pensais que celui-ci était particulièrement chouette:
Le _
miroir dans le coin supérieur droit est d’abord un no-op, nous imprimons avec !
et appuyons sur le <
. Le 0
chemin frappe maintenant le miroir horizontal et se termine. Le 1
chemin prend une trajectoire très intéressante cependant: il dévie vers le bas, enveloppements au !
, est redirigé vers l'horizontale et enveloppe puis de nouveau à la !
fois . Il continue ensuite à avancer dans cette forme de losange, en imprimant deux fois par itération (tous les trois tics).
Groupe 8
C'est l'une des deux solutions avec une boucle d'impression très serrée:
Le <
agit comme la branche. Après avoir emballé deux fois, 0
frappe @
. 1
d'autre part, saute d'abord le ?
, puis l' >
envoie à $
nouveau, donc saute le @
. Ensuite, l’IP s’enroule dans le chemin turquoise, où il rebondit entre le >
et <
((entourant le bord entre les deux).
Groupe 10
L'un des deux groupes qui utilisent d'autres pointeurs d'instructions, et c'est absolument magnifique. Hexagony en a 6 - chacun part d'un coin différent le long du bord des aiguilles d'une montre, mais un seul d'entre eux est actif à la fois.
Comme d'habitude, on lit avec ?
. La ~
négation est maintenant unaire: elle transforme le 1
en -1
. Ensuite, nous avons frappé le #
. C'est un moyen de basculer entre les adresses IP: il prend la valeur de front actuelle modulo 6 et bascule sur l'adresse IP correspondante (les adresses IP sont numérotées 0
dans le sens des aiguilles d'une montre). Donc, si l’entrée était la suivante 0
, l’adresse IP reste simplement la même et se déplace ennuyeusement droit devant elle !@
. Mais si l'entrée était 1
, alors la valeur actuelle est -1
ce qui est 5 (mod 6)
. Nous passons donc à l’IP qui commence sur la même cellule (le chemin vert). Now #
est un no-op et ?
définit le bord de la mémoire à 0
. )
incrémente donc !
imprime a 1
. Maintenant, nous avons ~
encore frappé pour nous assurer que#
est toujours un no-op (par opposition à nous passer à IP 1 qui mettrait fin au programme). C'est incroyable de voir à quel point tout concorde dans ce petit programme.
Groupe 22
Il est juste de noter que c’est le groupe dans lequel se trouve ma solution initiale. Il s’agit également du groupe le plus important, car le no-op peut se trouver à deux endroits différents et il existe plusieurs choix pour la commande réelle (no-op effective).
Groupe 23
C'est l'autre groupe qui utilise plusieurs adresses IP. En fait, celui-ci utilise 3 adresses IP différentes. Le coin en haut à droite est un peu en désordre, mais je vais essayer de vous expliquer:
Ainsi, le début que vous avez vu auparavant: <
dévie le nord-est, ?
lit les entrées. Il ]
existe maintenant un autre moyen de changer d’adresse IP: il passe le contrôle à la prochaine adresse IP dans le sens des aiguilles d’une montre. Nous passons donc le contrôle sur le chemin turquoise qui (je sais que c'est difficile à voir) commence dans le coin nord-est en direction du sud-est. Cela se reflète immédiatement <
dans le coin sud-est, en direction nord-ouest. Il frappe également le ]
donc nous passons à la prochaine adresse IP. C'est le chemin gris qui commence dans le coin est et se dirige vers le sud-ouest. Il imprime l'entrée, puis passe au coin nord-est. <
dévie le chemin dans l'horizontale, où il est reflété par l' autre <
. Maintenant la main droite<
agit comme une branche: si l’entrée était 0
, l’IP se déplace vers le nord-est, et encapsule vers le @
. Si l'entrée était 1
, l'IP se déplace vers le !
, enveloppe le le-thand <
où il est reflété ... maintenant dans le coin, il retourne vers le !
, est dévié par la droite <
, reflété par la gauche <
et les chemins commencent plus de...
Tout un gâchis, mais un beau gâchis. :)
Diagrammes générés avec l' étonnant HexagonyColorer de Timwi .