<
,,}:?
.
;(" {(={}{".
,",;=};} }) "{@
L'entrée est N
suivie de la chaîne, séparée par tout caractère non numérique.
Essayez-le en ligne!
Cela a été écrit en collaboration avec Sp3000 (ce qui signifie que je ne pouvais pas être dérangé pour trouver un algorithme, alors il a commencé à travailler dessus, a trouvé une solution de 118 octets mais ne pouvait pas être dérangé par le golf, alors j'ai fait le golf. .. yay pour le travail d'équipe).
Explication
Primaire habituel de Sp (comme d'habitude légèrement modifié):
- Labyrinth est un langage 2D basé sur une pile avec deux piles, principale et auxiliaire. Presque tout se passe sur la pile principale, mais vous pouvez déplacer les valeurs sur l'autre, par exemple pour les inverser ou les enregistrer pour plus tard.
- Les piles sont sans fond et remplies de zéros, donc sauter d'une pile vide n'est pas une erreur.
- L'exécution commence à partir du premier caractère valide (ici en haut à gauche). À chaque jonction, où il y a deux ou plusieurs chemins possibles que le pointeur d'instruction (IP) doit prendre, le haut de la pile est vérifié pour déterminer où aller ensuite. Négatif est tourner à gauche, zéro est aller de l'avant et positif est tourner à droite. Bien que cela ait été conçu pour donner au code l'apparence de passages sinueux et sinueux, rien ne vous empêche de créer des "pièces" où ces conditions sont vérifiées dans chaque cellule. Ceux-ci peuvent produire un comportement assez imprévisible, mais sont parfaits pour le golf.
- Le code source (et donc la disposition du labyrinthe) peut être modifié lors de l'exécution à l'aide de
<>^v
ce qui décale cycliquement une ligne ou une colonne ou la grille.
"
ne sont pas opérationnels.
Et c'est parti.
Le code commence le <
, ce qui est une astuce de golf que j'ai utilisée à quelques reprises pour commencer avec un long morceau de code linéaire. Il décale la première ligne cycliquement vers la gauche, avec l'IP dessus , donc la source ressemble alors à ceci:
<
,,}:?
.
;(" {(={}{".
,",;=};} }) "{@
Mais maintenant, l'IP ne peut plus se déplacer, donc il exécute à <
nouveau. Cela continue jusqu'à ce que nous atteignions cet état:
<
,,}:?
.
;(" {(={}{".
,",;=};} }) "{@
À ce stade, l'IP peut quitter la cellule et commencer à exécuter la deuxième ligne à partir de ?
. Voici donc le code linéaire décomposé:
? # Read the first integer on STDIN, i.e. N.
:} # Duplicate it and move one copy over to the auxiliary stack.
, # Read the separator character.
,. # Read the first character of the input string and directly print it.
L'IP entre maintenant dans cette salle 3x2, qui est en fait deux boucles compressées étroitement (se chevauchant) 2x2 dans le sens des aiguilles d'une montre. La première boucle lit et supprime les N-1
caractères de STDIN.
; # Discard the top of the stack. On the first iteration, this is the
# separator we've already read. On subsequent iterations this will be
# one of the N-1 characters from the input string.
( # Decrement N. If this hits zero, we leave the loop, otherwise we continue.
, # Read the next character from STDIN to be discarded.
Maintenant, nous entrons dans la deuxième boucle qui lit le reste de la chaîne d'entrée. Nous pouvons détecter EOF car ,
reviendra -1
dans ce cas, faisant tourner l'IP à gauche.
, # Read a character. Exit the loop if EOF.
( # Decrement it.
Ce décrément n'est pas vraiment utile, mais nous pouvons l'annuler plus tard gratuitement et ici il nous permet de chevaucher les deux boucles.
Si nous prenons l' 5 ABCDEFGHIJKLMNOP
exemple en entrée, la pile ressemble à ceci:
Main [ ... 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O' -1 | 5 ... ] Auxiliary
Notez que ceux-ci correspondent en fait aux caractères d'entrée FGHIJKLMNOP
(parce que nous les avons décrémentés), et que nous ne voulons pas réellement imprimer le premier de ceux-ci (nous avons seulement supprimé les N-1
caractères, mais nous voulons les ignorerN
).
Maintenant, il y a un petit bit linéaire qui prépare la pile pour la prochaine boucle:
; # Discard the -1.
= # Swap the tops of the stacks, i.e. N with the last character.
# By putting the last character on the auxiliary stack, we ensure that
# it doesn't get discarded in the next loop.
} # Move N over to the auxiliary stack as well.
Les piles ressemblent maintenant à:
Main [ ... 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' | 5 'O' ... ] Auxiliary
Nous entrons dans une autre boucle 2x2 dans le sens horaire. Cela supprime les premiers N
personnages de la pile principale:
; # Discard the top of the main stack.
{ # Pull N over from the auxiliary stack.
( # Decrement it. It it's 0 we leave the loop.
} # Push N back to the auxiliary stack.
Lorsque nous quittons la boucle, cela =
permute à nouveau 0
le dernier caractère de la chaîne d'entrée. Maintenant, les piles ressemblent à ceci:
Main [ ... 'E' 'F' 'G' 'H' 'I' 'O' | ... ] Auxiliary
Nous voulons imprimer le contenu de la pile principale (sauf l'élément du bas et tous incrémentés de 1), à partir de la gauche . Cela signifie que nous devons le transférer vers la pile auxiliaire. C'est ce que fait la prochaine boucle 2x2 (dans le sens des aiguilles d'une montre):
{ # Pull an element over from the auxiliary stack. This is necessary so we
# have a 0 on top of the stack when entering the loop, to prevent the IP
# from turning right immediately.
} # Move the top of the main stack back to the auxiliary stack. If this was the
# bottom of the stack, exit the loop.
) # Increment the current character.
} # Move it over to the auxiliary stack.
Empile maintenant:
Main [ ... | 'F' 'G' 'H' 'I' 'J' 'P] ... ] Auxiliary
Nous replaçons le premier (celui avec lequel nous ne voulons pas imprimer) dans la pile principale {
. Et maintenant, nous entrons dans la boucle finale 2x2 ( antihoraire ), qui imprime le reste:
{ # Pull another character over from the auxiliary stack. Exit the loop
# if that's the zero at the bottom of the stack.
. # Print the character.
Enfin, nous terminons le programme avec @
.
'
le personnage de comptage? Par exemple''123321
:?