Labyrinthe , 28 25 24 23 22 octets
" >
?!?:|}\{@
@\?"":)!
C'était amusant fou! :) C'est de loin le programme Labyrinthe le plus densément compressé que j'ai écrit jusqu'à présent. J'avais tellement de versions à 20 et 21 octets qui fonctionnaient presque que je doute toujours que ce soit optimal ...
Cela prend l'entrée comme une liste d' entiers positifs (avec un délimiteur arbitraire) et imprime le résultat dans STDOUT sous forme d'entiers délimités par des sauts de ligne.
La chasse aux 20/21 octets: j'ai vérifié tous les programmes du formulaire
" XX
?!?X}\{@
@\?XX)!
où X
est tout caractère raisonnable par force brute, mais n'a trouvé aucune solution valide. Bien sûr, cela ne signifie pas qu'il n'existe pas de solution plus courte, mais il n'est pas possible de forcer des programmes de 20 octets sans une quantité décente d'hypothèses sur sa structure.
Explication
(L'explication est légèrement dépassée, mais je ne suis toujours pas convaincu que la solution soit optimale, donc j'attendrai avec la mise à jour.)
Donc, normalement, les programmes Labyrinth sont censés ressembler à des labyrinthes. Pendant que le pointeur d'instructions se trouve dans un couloir, il suivra ce couloir. Lorsque l'IP atteint n'importe quel type de jonction, la direction est déterminée en fonction de la valeur maximale de la pile principale de Labyrinth (Labyrinth a deux piles, avec une quantité infinie de zéros en bas). Cela signifie normalement que toute boucle non triviale sera assez coûteuse, car si vous avez des cellules non murales partout, tout est une jonction, et dans la plupart des cas, le haut de la pile n'aura pas la bonne valeur pour l'IP pour prendre le chemin que vous aimeriez qu'il prenne. Donc, ce que vous faites, c'est agrandir les boucles de sorte qu'elles aient un tout au centre avec un seul point d'entrée et de sortie bien défini chacun.
Mais cette fois, j'ai vraiment eu de la chance et tout allait si bien ensemble que je pouvais tout écraser en une seule grosse touffe. :)
Le flux de contrôle commence au _
sud. Le _
pousse un zéro sur la pile principale. Cela peut sembler être un no-op, mais cela augmente la profondeur de pile (non implicite) 1
dont nous aurons besoin plus tard.
?
lit un entier dans STDIN. S'il n'y a plus d'entiers à lire, cela pousse zéro. Dans ce cas, l'IP continue de se déplacer vers le sud et @
termine immédiatement le programme (car la liste d'entrée est vide). Sinon, l'IP tourne vers l'Est.
Nous entrons maintenant dans une boucle très serrée avec deux points de sortie:
!?;
\?
;
!
imprime l'entier dans STDOUT, ne laissant qu'un zéro sur la pile. L'IP continue de se déplacer vers l'est et ?
lit l'entier suivant. Si ce n'est pas zéro, nous prenons à droite et nous nous déplaçons vers le sud. ?
lit un autre (le prochain index pair). Encore une fois, si ce n'est pas zéro, nous prenons à droite et nous nous déplaçons vers l'ouest.
\
Imprime ensuite un saut de ligne sans changer la pile, nous prenons donc une autre à droite en se déplaçant vers le nord. !
imprime le prochain entier d'index pair. Comme il y a maintenant au moins un entier impair (positif) sur la pile, nous continuons à tourner à droite et la boucle se répète.
Une fois que l'un d'eux ?
atteint la fin de la liste, il pousse un zéro et se déplace directement sur le correspondant ;
, ce qui rejette ce zéro.
Dans le cas où il n'y avait qu'un seul élément dans la liste, nous avons terminé (parce que nous l'avons imprimé tout de suite), donc l'IP continuerait de se déplacer vers l'est jusqu'à la @
fin du programme (en imprimant une fin saut de ligne en chemin).
Sinon, nous devons également imprimer les entiers à indice impair. Dans ce cas, les deux chemins (à partir des deux points de sortie de la première boucle) fusionnent au milieu "
, tournant vers l'Est dans les deux cas.
_
pousse un zéro pour éviter de prendre une gauche dans le @
, et ;
rejette ce zéro. Maintenant, nous entrons dans une nouvelle boucle:
"}
""
L'IP entre dans la cellule en bas à gauche, se déplaçant vers le nord, faisant le tour de la boucle dans le sens des aiguilles d'une montre. Le }
déplace le haut de la pile principale vers la pile auxiliaire. Bien qu'il y ait encore un élément sur la pile, l'IP continue de faire son travail. Une fois que tout a été déplacé vers la pile auxiliaire (et inversé dans le processus), l'IP continue de se déplacer vers l'est à la place, entrant dans la dernière boucle:
\{@
#!
\
imprime à nouveau un saut de ligne, {
déplace un élément de la pile auxiliaire vers le principal. Si c'était encore un élément de la liste, il sera positif et l'adresse IP se dirigera vers le sud, là où l'élément est imprimé !
. #
Pousse ensuite la profondeur de pile (et maintenant c'est là que l'initiale _
est importante, car cela #
garantit une profondeur de pile positive), de sorte que l'IP tourne toujours à droite, à travers le \
et à {
nouveau.
Une fois que nous avons tout imprimé, tiré {
un zéro du bas de la pile auxiliaire, l'IP continue vers l'Est et @
termine le programme.