Tarea
Lea en una secuencia o archivo de texto posiblemente infinito, generando su contenido hasta que hello
se haya emitido la palabra , respetando las siguientes reglas.
Una vez que
hello
se ha emitido, su código debe salir inmediatamente No debe esperar una nueva línea, por ejemplo.Su código debería salir a medida que avanza. Es decir, no debería leer una gran cantidad de entrada y luego comenzar a salir.
Si la secuencia / archivo no contiene
hello
, su código debería continuar enviando la entrada para siempre o hasta que se llegue al final de la secuencia / archivo.Este es un desafío sensible a mayúsculas y minúsculas, por
hello
lo que no es igual aHello
.Puede suponer que la entrada consiste únicamente en caracteres ASCII imprimibles y líneas nuevas.
Su código no puede esperar que el texto sea terminado por una nueva línea o que haya alguna nueva línea en la entrada. Además, su código no puede suponer que se ejecutará en una máquina con una cantidad infinita de memoria.
Puede suponer que se llamará a su código desde un directorio vacío.
Ejemplo de flujo de entrada
I once had a horse called hellopina.
Salida
I once had a horse called hello
Propina
Ejecute yes | tr -d \\n | <your program>
para verificar si funciona con flujos infinitos. Si no imprime nada y / o pierde memoria, el programa no cumple con las especificaciones. Debería imprimirse yyyyyyyyyyyyyyyyyyyyyy...
para siempre sin nuevas líneas.
Respuestas:
Jalea , 24 bytes
Pruébalo en línea!
Explicación:
fuente
C (gcc) ,
8180767572717069 bytesPruébalo en línea!
Cómo funciona
Este es un programa completo. Definimos una función f para nuestros propósitos. Para guardar bytes, se declara con dos argumentos que por defecto son int . Este es un comportamiento indefinido, pero en la práctica, n se inicializará como 1 cuando se ejecute el programa sin argumentos adicionales, c mantendrá los 32 bits inferiores del puntero al vector de argumento
Mientras la condición
sostiene, ejecutaremos el mientras que el cuerpo del bucle:
Para comprender completamente la condición, primero debemos examinar el cuerpo. Por ahora, todo lo que observamos es que
c=getchar()
lee un solo byte de STDIN (si es posible) y lo almacena en la variable c .La secuencia de bytes hola se ve de la siguiente manera en diferentes representaciones.
Todos estos se encuentran en el rango [96, 192) , por lo que
c/96
se evaluará a 1 para cada uno de estos bytes y a 0 para todos los caracteres ASCII restantes. De esta manera,putchar(c)/96*c
( putchar imprime y devuelve su argumento) evaluará a c si c es`
una letra minúscula, uno de{|}~
los caracteres DEL o; para todos los demás caracteres ASCII, se evaluará a 0 .n se actualiza desplazándolo cinco bits hacia la izquierda, luego XORingando el resultado con el resultado del párrafo anterior. Como un int tiene 32 bits de ancho (o eso suponemos en esta respuesta), algunos de los bits desplazados pueden "caerse a la izquierda" (el desbordamiento de entero con signo es un comportamiento indefinido, pero gcc se comporta como la instrucción x64 que genera aquí). Comenzando con un valor desconocido de n , después de actualizarlo para todos los caracteres de saludo , obtenemos el siguiente resultado.
Tenga en cuenta que los 25 bits inferiores forman el entero 0xb33def , que es la constante mágica en la condición. Si bien existe cierta superposición entre los bits de dos bytes adyacentes, la asignación de bytes por debajo de 96 a 0 asegura que no haya falsos positivos.
La condición consta de dos partes:
~(getchar())
toma el NO bit a bit del resultado de leer (o intentar leer) un byte de STDIN.Si getchar tiene éxito, devolverá el valor del byte de lectura como int . Dado que la entrada consiste completamente en caracteres ASCII, el byte de lectura solo puede tener sus 7 bits inferiores establecidos, por lo que el NO bit a bit tendrá sus 25 bits más altos establecidos en este caso.
Si getchar falla (no más entradas), devolverá -1 y el NO bit a bit será 0 .
n-0xb33def<<7
resta la constante mágica de antes de n , luego desplaza el resultado 7 unidades hacia la izquierda.Si los últimos 5 bytes leídos fueron hola , los 25 bits más bajos de n serán iguales a 0xb33def y la resta los pondrá a cero. Desplazar la diferencia producirá 0 ya que los 7 bits más altos "caerán por la izquierda".
Por otro lado, si los últimos 5 bytes leídos no fueron hola , se establecerá uno de los 25 bits más bajos de la diferencia; después del cambio, uno de los 25 bits más altos será.
Finalmente, si getchar tuvo éxito y aún no imprimimos hola , se establecerán los AND bit a bit, los 25 bits más altos del operando izquierdo y al menos uno de los 25 bits más altos del derecho. De esta manera,
&
producirá un número entero distinto de cero y el ciclo continuará.Por otro lado, si la entrada está agotada o ya hemos impreso hola , uno de los operandos AND de bit será cero, y también lo será el resultado. En este caso, salimos del ciclo y el programa termina.
fuente
Bash,
747510399888276 bytes-10 bytes gracias a @DigitalTrauma!
-11 bytes gracias a @manatwork!
-6 bytes gracias a @Dennis!
Explicación:
Pruébalo en línea!
fuente
Laberinto ,
4341 bytesGracias a Sp3000 por guardar 2 bytes.
Pruébalo en línea!
Explicación
La idea básica es codificar los últimos cinco caracteres en base 256 en un solo entero. Cuando entra un nuevo carácter, podemos "agregarlo" multiplicando el entero por 256 y agregando el nuevo punto de código. Si queremos ver solo los últimos 5 caracteres, tomamos el valor módulo 256 5 = 2 40 = 1099511627776. Luego, simplemente podemos verificar si este valor es igual a 448378203247, que es lo que obtenemos cuando tratamos los puntos de código de
hello
como base de 256 dígitos.En cuanto al código ...
<...>
es un poco un idioma laberinto. Le permite escribir un bucle infinito sin ningún flujo de control condicional en una sola línea, ahorrando muchos bytes en espacios y saltos de línea. La condición principal para que esto funcione es que hay dos valores desechables en la parte superior de la pila cuando llegamos a<
(normalmente usamos0
s para eso, pero el valor real es arbitrario).Por supuesto, el programa necesita cierta lógica condicional para determinar cuándo terminar. Pero es posible terminar condicionalmente el programa dividiendo por un valor que es cero cuando queremos que el programa finalice. La
<...>
construcción funciona desplazando toda la fila hacia la izquierda (cíclicamente) cuando la IP está en el extremo izquierdo, y luego volviéndola inmediatamente a su posición. Esto significa que el código se ejecuta de derecha a izquierda. Vamos a revertirlo:Esta es una iteración del ciclo que lee un carácter, termina si hemos alcanzado EOF, imprime el carácter, lo agrega a nuestra codificación, lo trunca a 5 caracteres, verifica la igualdad con
hello
y se repite. Así es como funciona en detalle (recuerde que Labyrinth está basado en la pila):fuente
Brainfuck, 658 bytes
Más de 500 bytes están en las constantes que necesito para jugar un poco.
Esencialmente es una máquina de estados, por lo que la entrada infinita no es un problema.
Esta es la versión ligeramente comentada
fuente
ahehellob
correctamente; en medio de una posible coincidencia, solo verifica la siguiente letrahello
y no busca unah
para comenzar de nuevo.Bash ,
736866 bytesAsume un directorio sin o solo archivos ocultos. Debe ejecutarse como
<path/to/script>
.Pruébalo en línea!
Cómo funciona (anticuado)
Al comienzo del tiempo de bucle, primero se prueba si la cadena en la variable s (inicialmente vacía) es igual a olleh ( hola al revés, olé), y devolver 0 (partido) o 1 (no es un partido) en consecuencia. Si bien formalmente es parte de la condición del bucle, el resultado no lo afectará por sí solo, ya que solo el último comando antes
do
determina si la condición se cumple.A continuación, configuramos el separador de campo interno en la cadena vacía (por
read
lo que no se ahogará en el espacio en blanco), leeremos bytes sin procesar (-r
) de STDIN y los almacenaremosc
.$?
es el código de salida del comando anterior, por lo que lee exactamente un-N1
byte ( ) para una no coincidencia y cero bytes (-N0
). La lectura de cero bytes, ya sea por golpear EOF o porque-N0
se especificó, haceread
que salga con el código de estado 1 , por lo que el ciclo while finalizará; de lo contrario, el cuerpo se ejecuta y comenzamos de nuevo.En el cuerpo, primero imprimimos el byte que leemos, luego actualizamos s con
s=$c${s::4}
. Esto antepone el byte de lectura a (hasta) los primeros cuatro bytes en s , por lo que s será igual a olleh una vez que se haya impreso hola .fuente
brainfuck, 117 bytes
Formateado:
Pruébalo en línea .
Esto inicializa la cinta con los caracteres en
hello
desplazamiento107
, espaciados con un valor cada tres celdas, luego realiza un seguimiento de los últimos cinco caracteres vistos y comprueba una coincidencia con cada nuevo carácter procesado, utilizando una bandera a la derecha de la cadena para realizar un seguimiento de si ha habido una coincidencia.fuente
Ruby ,
4660 bytesPruébalo en línea!
Lee caracteres de stdin hasta que los últimos 5 son
hello
, luego genera la cadena (o hasta que no quedan caracteres en stdin). Termina con error.Equivalente a:
O, más descabellado:
fuente
a
crece cada vez que se lee un personaje. ¿Se bloquea esto si la entrada es infinita?Pitón 3,
120116104 BytesFunciona con corrientes infinitas, golf por primera vez, cualquier consejo es apreciado.
Gracias @DJMcMayhem por guardar algunos bytes :)
fuente
c=[0,c+1]['hello'[c]==a]
debería ahorrarte algunos bytes. Además,a=1
es más corto también.while
en Python.Haskell,
414743 bytesLa pereza de Haskell maneja bien la entrada / salida infinita.
Pruébalo en línea!
Editar: no manejó la entrada finita - arreglado. Gracias @ Leo por señalar.
Editar II: @ Ørjan Johansen guardó 4 bytes. ¡Gracias!
fuente
|w@"hello"<-take 5l=w
.Cubix,
94 83 82 79 6356 bytesExpandido:
Notas
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
, luegoe
, 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 (
.
):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
[...]
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.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 empujarh
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]
.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 yh
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 ese
,0
si la entrada esh
,4
si la entrada esl
y7
si la entrada eso
.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 fuee
, por lo que el siguiente carácter debería ser unl
. Si la IP continúa en línea recta, la diferencia fue0
, por lo que la entrada fueh
, por lo que el siguiente carácter debería ser une
. Si la entrada es anl
o ano
, la IP gira a la derecha.Todas las instrucciones ejecutadas antes del signo de interrogación antes mencionado son:
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.Los caracteres se ejecutan en este orden (excluyendo algunos caracteres de flujo de control):
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.Las instrucciones ejecutadas son:
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 elo
, 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 paral
y que tenemos que finalizar el programa si la entrada fue uno
. 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.Discernir entre los dos
'l'
sEntonces, ahora sabemos que la entrada fue un
l
, pero no sabemos cuáll
. Si es el primero, necesitamos empujar a otrol
al final de la pila, pero si es el segundo, debemos empujar uno
. ¿Recuerdas que guardamos-3
en la parte inferior de la pila justo antes de presionar el primerol
? Podemos usar eso para separar las dos ramas.La pila comienza como
[..., -3 or 140, ...]
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.Se ejecutan las siguientes instrucciones:
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.Las instrucciones ejecutadas son:
Y la IP está a punto de ingresar al ciclo de lectura / escritura nuevamente, por lo que también hemos terminado con esta rama.
fuente
C ++,
142141 bytesPruébalo en línea!
fuente
#import
en los programas de GCC C ++ ...#import
es una extensión GCC obsoleta.Nodo, 124 bytes
Sin suponer que la secuencia se ajustará en la memoria disponible.
fuente
C #, 134 bytes
Pruébalo en línea
Lee un carácter, comprueba que no es -1 (EOS) y que todavía no hemos visto "hola", luego lo antepone a una cadena y escribe el carácter. Anteponemos porque
s[0]
es mucho más corto que(char)s
. Esto tiene un costo cuadrático en la longitud de la cadena, ya que tiene que asignar y escanear toda la entrada cada vez que lee un carácter (esto se bloqueará después de 2GB de entrada debido a restricciones en el CLR, ¿está permitido?)Para una versión (más larga: 142 bytes) que no quedará sin memoria y que tiene un costo constante por carácter, consulte a continuación:
Este mantiene los últimos 5 caracteres en una cadena de 5 longitudes, lo que significa comparaciones cortas y búsquedas económicas de last-char, pero es considerablemente más costoso de actualizar.
fuente
PHP,
57 5553 bytesComo no hay archivos infinitos, tomo información de STDIN. Corre con
-nr
.Recorra la entrada, imprima el carácter actual, añádalo
$s
, corte$s
los últimos 5 caracteres. Romper el ciclo cuando$s
eshello
.fuente
Vim, 39 bytes
Pruébalo en línea!
fuente
PowerShell, 111 bytes
Probablemente haya una mejor manera de hacer esto, pero no puedo verla en este momento.
Esto lee las pulsaciones de teclas sin suprimir el eco. El carácter se agrega a $ x, que se recorta a los últimos 5 caracteres y se compara con "hola". Esto continúa hasta que la comparación sea verdadera.
Nota: esto no funciona en PowerShell ISE. ReadKey está deshabilitado en ese entorno.
fuente
Esquema 115 bytes
Versión legible:
Esto toma un carácter individual de stdin cada vez alrededor del bucle y marca su posición en la palabra objetivo cuando se encuentra con los caracteres de "hola".
Se detiene cuando se agota la entrada o se ha visto "hola". No se utiliza memoria en flujo infinito.
fuente
AWK, 95 bytes
Hay 2 cosas que aprendí aquí:
1) Para dividir registros entre caracteres, use
RS="(.)"
y luegoRT
debe usarse en lugar de$1
2)
ORS
es usado porprint
y está predeterminado en"\n"
3) No puedo contar hasta 2 y el uso
printf
es "más barato" que asignarORS
y utilizandoprint
Ejemplo de uso: colocar el código en ARCHIVO
o
El código se probó utilizando la
yes | ...
sugerencia de Dennis y vi muchísimasy
.Para su información, puede hacer la asignación de RS como una opción y sacarla del
BEGIN
bloque a través de:fuente
BEGIN{RS="(.)"}{printf RT}"olleh"==a=RT substr(a,1,4){exit}
.Python 3 (Linux),
7372 bytes¡Gracias a @MitchSchwartz por jugar golf en 1 byte!
Pruébalo en línea!
fuente
while
evalúa la condición para evaluar adecuadamente? Parece que estás comparando un booleano con una cadena vacía.s[print(end=c):4]
guarda un byte'olleh'!=s and s>''and''<c)
. La prueba intermedia no es necesaria, pero encadenarlos es más corta que la sencilla'olleh'!=s and''<c
.Código de máquina 8086, 22 bytes
Código de ensamblaje equivalente:
fuente
Pyth,
4947 bytesPyth no es muy bueno para tomar un solo carácter de entrada. Todo en
$__import__("sys").stdin.read(1)
eso es simplemente hacer eso. Además, significa que esto solo se ejecuta sin conexión.Todo lo demás es corto ...
El programa es un bucle while sin cuerpo. Dentro de la condición, el programa lee un carácter, lo imprime de nuevo, agrega ese carácter a
k
(que inicialmente es la cadena vacía), recorta todos menos los últimos 5 caracteresk
y luego comprueba que el resultado no lo es"hello"
.32 caracteres obtienen un byte de entrada, 15 caracteres hacen el resto.
Probado en Linux, funciona incluso sin línea nueva, entrada infinita, etc.
fuente
Lua,
6864 bytesfuente
l:sub(-4)
, luego puede reducir la inicialización del=""
.Ruby,
59494843 bytesAhora sin despotricar, más corto y sin pérdida de memoria.
Ahorró 5 bytes al eliminar algunos paréntesis y un espacio gracias a Dennis
fuente
röda ,
4947 bytesPruébalo en línea!
Esta es una función anónima que lee los caracteres de su flujo de entrada y los emite hasta que se encuentra "hola". Utiliza la matriz.
a
para rastrear los últimos caracteres.Emite algo de basura a STDERR, pero entendí que es permitido .
Explicación:
fuente
Java 7,
122118124123150141 bytesAhora se detiene cuando se alcanza el final de la secuencia. Ahora maneja la entrada infinita sin quedarse sin memoria.
fuente
write
se usara en lugar deprint
. No puedo deshacer mi voto negativo, lo siento :(Ruby, 51 bytes
fuente
AHK , 116 bytes
No hay nada inteligente o mágico allí, realmente. La variable
%1%
es el primer argumento pasado y debe ser una ruta de archivo con la secuencia. El archivo debe guardarse a medida que se actualiza, pero el código se leerá hasta el final, incluso si se expande después de que comience la lectura.fuente
Mathematica, 107 bytes
La salida se convierte en un campo donde el usuario puede escribir texto infinitamente (incluidas las nuevas líneas) hasta que los últimos 5 caracteres sean iguales
"hello"
; en ese punto, sale.fuente
brainfuck , 281 bytes
No estoy seguro de por qué, pero sentí que el cerebro era lo correcto para hacer esto. No requiere memoria infinita, y puede salir para siempre.
Explicado
Pruébalo en línea!
fuente
ahehellob
.