Cubix, 94 83 82 79 63 56 bytes
p>q'-?w.uh'e@U7.'hqi?oqB-!ul.-..$WWu_q<o'\;>....6t?.../!@
Expandido:
p > q '
- ? w .
u h ' e
@ U 7 .
' h q i ? o q B - ! u l . - . .
$ W W u _ q < o ' \ ; > . . . .
6 t ? . . . / ! @ . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Notas
- El intérprete deshabilita el campo de entrada cuando se inicia el programa. Como tal, un flujo infinito de entrada es imposible. Este programa toma la entrada carácter por carácter, por lo que si no fuera por esta limitación, funcionaría correctamente.
- Este programa no limpia la pila, y se desordena muy rápidamente. Como la máquina en la que se utilizará aparentemente puede proporcionar flujos de entrada infinitos, parece razonable suponer que también tiene memoria infinita.
- Cualquier y toda ayuda de golf es muy apreciada.
Pruébalo en línea
Puedes probar el programa aquí .
Explicación
Idea general
La idea general es que queremos leer un personaje y luego compararlo con varios caracteres (primero h
, luego e
, luegol
etc.). Para realizar un seguimiento del personaje que nos hemos perdido, lo mantenemos en la parte inferior de la pila. Cuando lo necesitamos, podemos llevarlo fácilmente a la cima nuevamente.
Bucle de lectura / escritura
El ciclo de lectura-escritura es simplemente la 5ª línea. Todos los caracteres que no se usan se reemplazan por no-ops ( .
):
. . . .
. . . .
. . . .
@ . . .
' h q i ? o q B - ! u l . - . .
. . . . _ . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Esto se puede dividir en dos partes: lectura y (escritura y verificación). La primera parte contiene las instrucciones hasta e incluyendo el signo de interrogación. La segunda parte es el resto de la línea. Debido a que esto se repite, asumimos que comenzamos con una pila 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 segunda parte (escribir y verificar) es lineal nuevamente. La pila comienza como [next-char, ..., input]
. Resumimos el siguiente personaje, porque eso cambia más adelante en el programa.
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.
Ahora, la IP comenzará nuevamente al comienzo de este ciclo, restableciendo el siguiente carácter para verificar h
.
Emparejando al siguiente personaje
Si la IP hizo un cambio de sentido (es decir, el carácter que leímos e imprimimos coincidía con el siguiente carácter 'hello'
), debemos verificar qué carácter era la entrada y, dependiendo de eso, empujar el siguiente carácter al final de la pila. Después de eso, necesitamos volver al ciclo de lectura / escritura, sin empujar h
a la pila, por lo que necesitamos otra forma de llegar allí.
Lo primero es lo primero: determinar qué carácter era la entrada. La pila es el siguiente: [..., prev-char, input, 0]
.
. . . .
- ? . .
u h ' e
. . . .
. . . . . . . . . ! u . . . . .
. . . . . . . . . \ ; . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Para comparar la entrada, usamos el código de caracteres de h
nuevo. Inicialmente, esto se debió a que realmente no sabía cómo iba a manejar esto y h
es el primer personaje en la cadena para verificar, pero terminó siendo bastante conveniente. Si restamos el código de caracteres de h de la entrada, obtenemos -3
si la entrada es e
, 0
si la entrada es h
, 4
si la entrada es l
y 7
si la entrada es o
.
Esto es útil, porque el ?
comando nos permite separar fácilmente los valores negativos de los valores positivos y cero. Como tal, si la IP gira a la izquierda, la diferencia fue negativa, por lo que la entrada fue e
, por lo que el siguiente carácter debería ser un l
. Si la IP continúa en línea recta, la diferencia fue 0
, por lo que la entrada fue h
, por lo que el siguiente carácter debería ser un e
. Si la entrada es an l
o an o
, la IP gira a la derecha.
Todas las instrucciones ejecutadas antes del signo de interrogación antes mencionado son:
;!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]
Ahora la IP cambia su dirección como se detalla anteriormente. Repasemos las diferentes posibilidades.
Entrada 'e'
Primero consideraremos la entrada e
, que hace que la IP se mueva hacia arriba desde ?
, ya que la diferencia es 3. Todos los caracteres irrelevantes se han eliminado del cubo.
. > q '
. ? . .
. . . .
. . . .
. . q . . . . . . . . l . . . .
$ W W . . . . . . . . > . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Los caracteres se ejecutan en este orden (excluyendo algunos caracteres de flujo de control):
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, ...]
Ahora la IP ha alcanzado el ciclo de lectura / escritura nuevamente.
Entrada 'h'
Si la entrada fue 'h'
, la diferencia es 0, por lo que la IP no cambia su dirección. Aquí está el cubo nuevamente, con todos los caracteres irrelevantes eliminados. Dado que esta ruta incluye bastantes no-ops, todas las no-ops que pasa han sido reemplazadas por &
. La IP comienza en el signo de interrogación.
. . . .
. ? w .
. . ' e
. . . .
. . . . . . . . . ! . . . . . .
. . . u _ q < . . \ . . . . . .
. . ? & & & / . . & . . . . . .
. . & . . . . . . & . . . . . .
. . . .
& & & &
. . . .
. . . .
Las instrucciones ejecutadas son:
'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
Y ahora estamos entrando en el ciclo de lectura / escritura nuevamente, así que hemos terminado.
Otras entradas
Todas las demás entradas dan como resultado una diferencia positiva, por lo que la IP gira a la derecha en el signo de interrogación. Todavía tenemos que separar el l
y el o
, así que eso es lo que haremos a continuación.
Separando el 'l'
y'o'
Tenga en cuenta que la diferencia es 7 para o
y 4 para l
y que tenemos que finalizar el programa si la entrada fue un o
. Aquí está el cubo nuevamente con las partes irrelevantes reemplazadas por a .
y los no-ops que la IP cruza han sido reemplazados por símbolos.
. . 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
Discernir entre los dos 'l'
s
Entonces, ahora sabemos que la entrada fue un l
, pero no sabemos cuál l
. Si es el primero, necesitamos empujar a otro l
al final de la pila, pero si es el segundo, debemos empujar un o
. ¿Recuerdas que guardamos -3
en la parte inferior de la pila justo antes de presionar el primero l
? Podemos usar eso para separar las dos ramas.
. . . .
. . . .
. . . .
. . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
6 t ? . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
La pila comienza como [..., -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
primero 'l'
Si este fue el primero 'l'
, tenemos que presionar a otro 'l'
. Para guardar bytes, usamos los mismos caracteres que para el primero 'l'
. Podemos simplificar la pila a [...]
. Aquí está la parte relevante del cubo, con las no-operaciones reemplazadas por símbolos de unión.
p > q '
. . . .
. . . .
. . . .
' . q . . . . . . . . l . . . .
$ W W . . . . . . . . > & & & &
. . ? . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Se ejecutan las siguientes instrucciones:
$'pq'lq
$' no-op
pq no-op
'l Push the character code of l
Stack: [..., 108]
q Send it to the bottom
Stack: [108, ...]
Estamos a punto de ingresar al ciclo de lectura / escritura, así que hemos terminado con esta rama.
Segundo 'l'
Si la entrada fue el segundo 'l'
en 'hello'
el IP giró a la derecha en el signo de interrogación. Una vez más, podemos simplificar la pila [...]
y la IP comienza en ?
, apuntando hacia el sur esta vez.
. . . .
. . . .
. . . .
. . . .
. . . . . . . . . . . . . . . .
. . . u _ q < o ' \ . . . . . .
. . ? . . . . . . & . . . . . .
. . & . . . . . . & . . . . . .
. . . .
& & & &
. . . .
. . . .
Las instrucciones ejecutadas son:
'oq_
'o Push the character code of 'o'
Stack: [..., 111]
q Move the top item to the bottom
Stack: [111, ...]
_ No-op
Y la IP está a punto de ingresar al ciclo de lectura / escritura nuevamente, por lo que también hemos terminado con esta rama.