Cubix, 94 83 82 79 63 56 octets
p>q'-?w.uh'e@U7.'hqi?oqB-!ul.-..$WWu_q<o'\;>....6t?.../!@
Étendu:
p > q '
- ? w .
u h ' e
@ U 7 .
' h q i ? o q B - ! u l . - . .
$ W W u _ q < o ' \ ; > . . . .
6 t ? . . . / ! @ . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Remarques
- L'interpréteur désactive le champ de saisie au démarrage du programme. En tant que tel, un flux d'entrée infini est impossible. Ce programme prend l'entrée caractère par caractère, donc s'il n'y avait pas cette limitation, il fonctionnerait correctement.
- Ce programme ne vide pas la pile et il devient très rapidement désordonné. Étant donné que la machine sur laquelle cela sera utilisé peut apparemment fournir des flux d'entrée infinis, il semble raisonnable de supposer qu'elle possède également une mémoire infinie.
- Toute aide au golf est très appréciée.
Essayez-le en ligne
Vous pouvez essayer le programme ici .
Explication
Idée générale
L'idée générale est que nous voulons lire un caractère, puis le comparer à différents caractères (d'abord h
, puis e
, puisl
etc.). Pour garder une trace du personnage que nous avons manqué, nous le gardons tout en bas de la pile. Lorsque nous en avons besoin, nous pouvons facilement le ramener au sommet.
Boucle de lecture / écriture
La boucle de lecture-écriture est simplement la 5 ème ligne. Tous les caractères non utilisés sont remplacés par no-ops ( .
):
. . . .
. . . .
. . . .
@ . . .
' h q i ? o q B - ! u l . - . .
. . . . _ . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Cela peut être divisé en deux parties: lecture et (écriture et vérification). La première partie contient les instructions jusqu'au point d'interrogation inclus. La deuxième partie est le reste de la ligne. Parce que cela tourne en boucle, nous supposons que nous commençons avec une pile de[...]
@
'hqi?
_
Explanation
'h Push the character code of the h
Stack: [..., 104]
q Send it to the bottom
Stack: [104, ...]
i Read one character of the input (-1 for EOF)
Stack: [104, ..., input]
? Start of condition:
if (input < 0):
@ execute '@', ending the program
if (input = 0):
continue going right
if (input > 0):
_ turn to the right, reflect back ('_') and
turn right again, effectively not changing
the direction at all
La deuxième partie (écriture et vérification) est de nouveau linéaire. La pile commence comme [next-char, ..., input]
. Nous avons résumé le caractère suivant, car cela change plus tard dans le programme.
oqB-!ul.- Explanation
o Output the character at the top of the stack
q Send the input to the bottom of the stack
Stack: [input, next-char, ...]
B Reverse the stack
Stack: [..., next-char, input]
- Push the difference of the top two characters, which
is 0 if both are equal, something else otherwise
Stack: [..., next-char, input, diff]
! if (diff = 0):
u make a u-turn to the right
else:
l. execute two no-ops
- push [input - next-char - input], which is disregarded
later, so it effectively is a no-op as well.
Maintenant, l'IP recommencera au début de cette boucle, réinitialisant le caractère suivant à vérifier h
.
Faire correspondre le caractère suivant
Si l'IP a fait demi-tour (c'est-à-dire que le caractère que nous avons lu et imprimé correspondait au caractère suivant 'hello'
), nous devons vérifier quel caractère était l'entrée et en fonction de cela, pousser le caractère suivant au bas de la pile. Après cela, nous devons retourner à la boucle de lecture / écriture, sans pousser h
vers la pile, nous avons donc besoin d'un autre moyen pour y arriver.
Tout d'abord: déterminez le caractère de l'entrée. La pile ressemble à ceci: [..., prev-char, input, 0]
.
. . . .
- ? . .
u h ' e
. . . .
. . . . . . . . . ! u . . . . .
. . . . . . . . . \ ; . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Pour comparer l'entrée, nous utilisons à nouveau le code de caractère de h
. Au départ, c'était parce que je ne savais pas vraiment comment j'allais gérer cela et h
c'est le premier caractère de la chaîne à vérifier, mais cela s'est avéré assez pratique. Si nous soustrayons le code de caractère de h de l'entrée, nous obtenons -3
si l'entrée est e
, 0
si l'entrée est h
, 4
si l'entrée est l
et 7
si l'entrée l'est o
.
C'est utile, car la ?
commande nous permet de séparer facilement les valeurs négatives des valeurs positives et zéro. En tant que tel, si l'IP tourne à gauche, la différence était négative, donc l'entrée était e
, donc le caractère suivant devrait être un l
. Si l'IP continue d'aller tout droit, la différence était 0
, donc l'entrée était h
, donc le caractère suivant devrait être un e
. Si l'entrée est un l
ou un o
, l'IP tourne à droite.
Toutes les instructions exécutées avant le point d'interrogation susmentionné sont:
;!e'h- Explanation
; Delete the top of the stack
Stack: [..., prev-char, input]
! if (input = 0):
e execute 'e' (no-op)
'h Push the character code of h
Stack: [..., prev-char, input, 104]
- Push the difference of the input and 104
Stack: [..., prev-char, input, 104, diff]
Maintenant, l'IP change de direction comme détaillé ci-dessus. Passons en revue les différentes possibilités.
Contribution 'e'
Nous allons d'abord considérer l'entrée e
, ce qui fait que l'IP se déplace vers le haut depuis le ?
, car la différence est de 3. Tous les caractères non pertinents ont été supprimés du cube.
. > q '
. ? . .
. . . .
. . . .
. . q . . . . . . . . l . . . .
$ W W . . . . . . . . > . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Les caractères sont exécutés dans cet ordre (à l'exception de certains caractères de flux de contrôle):
q'l$WWq
q Save the difference (-3) to the bottom of the stack so
we can tell whether the l on the bottom of the stack is
the first or the second l in hello
Stack: [-3, ...]
'l Push the character code of l to the stack
Stack: [-3, ..., 108]
$W no-op
W Sidestep into the loop
q Send the character code to the bottom
Stack: [108, -3, ...]
Maintenant, l'IP a de nouveau atteint la boucle de lecture / écriture.
Contribution 'h'
Si l'entrée était 'h'
, la différence est 0, donc l'IP ne change pas de direction. Voici à nouveau le cube, avec tous les caractères non pertinents supprimés. Puisque ce chemin comprend pas mal d'opérations, toutes les opérations qu'il passe ont été remplacées &
. L'IP commence au point d'interrogation.
. . . .
. ? w .
. . ' e
. . . .
. . . . . . . . . ! . . . . . .
. . . u _ q < . . \ . . . . . .
. . ? & & & / . . & . . . . . .
. . & . . . . . . & . . . . . .
. . . .
& & & &
. . . .
. . . .
Les instructions exécutées sont les suivantes:
'e!\?q_
'e Push the character code of the e
Stack: [..., 101]
! if (101 = 0):
\ reflect away (effectively a no-op)
? if (101 > 0):
turn right (always happens)
q Move 101 to the bottom of the stack
Stack: [101, ...]
_ No-op
Et maintenant, nous entrons à nouveau dans la boucle de lecture / écriture, nous avons donc terminé.
Autres entrées
Toutes les autres entrées entraînent une différence positive, donc l'IP tourne à droite au point d'interrogation. Nous devons encore séparer le l
et leo
, c'est donc ce que nous ferons ensuite.
Séparer le 'l'
et'o'
Gardez à l'esprit que la différence est de 7 pour o
et 4 pour l
et que nous devons mettre fin au programme si l'entrée était un o
. Voici à nouveau le cube avec les parties non pertinentes remplacées par un .
et les no-ops que les croisements IP ont été remplacés par des esperluettes.
. . q .
. ? w .
. h ' .
. U 7 .
. . . . . . . . . . . . . - . .
. . . . . . . . . . . . . & . .
. . . . . . / ! @ . . . . & . .
. . . . . . & . . . . . . & . .
. . & .
. . & .
. . & .
. . & .
h7'wq-!@
h no-op
7 Push 7 to the stack
Stack: [..., diff, 7]
'wq Push w to the stack and send it to
the bottom. We don't care about it,
so it's now part of the ellipsis.
Stack: [..., diff, 7]
-! if (diff = 7):
@ End the program
Discerner entre les deux 'l'
s
Donc, maintenant nous savons que l'entrée était un l
, mais nous ne savons pas lequel l
. Si c'est le premier, nous devons en pousser un autre l
au bas de la pile, mais si c'est le second, nous devons pousser un o
. Rappelez-vous que nous avons enregistré -3
au bas de la pile juste avant de pousser le premier l
? Nous pouvons l'utiliser pour séparer les deux branches.
. . . .
. . . .
. . . .
. . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
6 t ? . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
La pile commence comme [..., -3 or 140, ...]
Explanation
6t?
6t Take the 6th item from the top and move
it to the top (which is either -3 or 140)
? If that's positive, turn right, otherwise,
turn left
Première 'l'
Si ce fut le premier 'l'
, nous devons en pousser un autre 'l'
. Pour économiser des octets, nous utilisons les mêmes caractères que pour le premier 'l'
. Nous pouvons simplifier la pile [...]
. Voici la partie pertinente du cube, avec aucune opération remplacée par des esperluettes.
p > q '
. . . .
. . . .
. . . .
' . q . . . . . . . . l . . . .
$ W W . . . . . . . . > & & & &
. . ? . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Les instructions suivantes sont exécutées:
$'pq'lq
$' no-op
pq no-op
'l Push the character code of l
Stack: [..., 108]
q Send it to the bottom
Stack: [108, ...]
Nous sommes sur le point d'entrer dans la boucle de lecture / écriture, nous avons donc terminé avec cette branche.
Seconde 'l'
Si l'entrée était le deuxième 'l'
dans 'hello'
l'IP a tourné à droite au point d'interrogation. Encore une fois, nous pouvons simplifier la pile [...]
et l'IP commence à ?
, pointant cette fois vers le sud.
. . . .
. . . .
. . . .
. . . .
. . . . . . . . . . . . . . . .
. . . u _ q < o ' \ . . . . . .
. . ? . . . . . . & . . . . . .
. . & . . . . . . & . . . . . .
. . . .
& & & &
. . . .
. . . .
Les instructions exécutées sont les suivantes:
'oq_
'o Push the character code of 'o'
Stack: [..., 111]
q Move the top item to the bottom
Stack: [111, ...]
_ No-op
Et l'IP est sur le point d'entrer à nouveau dans la boucle de lecture / écriture, nous avons donc terminé avec cette branche également.