Me tuviste en hola


30

Tarea

Lea en una secuencia o archivo de texto posiblemente infinito, generando su contenido hasta que hellose haya emitido la palabra , respetando las siguientes reglas.

  • Una vez que hellose 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 hellolo que no es igual a Hello.

  • 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.


1
¿Se nos permite leer algo después del "hola"? La pregunta parece prohibir cualquier lectura adicional, que podría ser problemática en lenguajes como (Estándar) C, que proporcionan una entrada almacenada en memoria intermedia con lectura anticipada automática.
Toby Speight el

Probablemente debería cambiar la respuesta aceptada a la del ensamblado, ya que es 2 bytes más corta.
Rɪᴋᴇʀ

@Riker Sería genial si alguien pudiera probarlo o al menos decir que cree que funciona primero.

Respuestas:


2

Jalea , 24 bytes

“Ṣẉ»ẇ⁸Ṇȧ®
ṫ-3;ƈ©Ȯ¤µ⁺Ç¿ṛ“

Pruébalo en línea!

Explicación:

ṫ-3;ƈ©Ȯ¤µ⁺Ç¿ṛ“ Main link. Arguments: 0
ṫ-3            Truncate the list to its 4 last elements.
   ;ƈ©Ȯ¤       Store a character from STDIN in the register, print it, and append it to the list (list is initially [0]).
        µ      Start a new monadic chain, everything to the left is a link.
          Ç    Execute the helper link with the existing list as its argument.
         ⁺ ¿   Do-while loop, left link is body, right link is condition.
            ṛ“ When the loop ends, replace the return value with [] (invisible on output).

“Ṣẉ»ẇ⁸Ṇȧ® Helper link. Arguments: string
“Ṣẉ»ẉ⁸Ṇ   Check if "hello" isn't in the string.
        ® Return the character we stored in the register.
       ȧ  Check if both of the above are truthy.

26

C (gcc) , 81 80 76 75 72 71 70 69 bytes

main(n,c){while(~(c=getchar())&n-0xb33def<<7)n=n<<5^putchar(c)/96*c;}

Prué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

~(c=getchar())&n-0xb33def<<7

sostiene, ejecutaremos el mientras que el cuerpo del bucle:

n=n<<5^putchar(c)/96*c

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.

char     decimal     binary (8 bits)
'h'      104         0 1 1 0 1 0 0 0
'e'      101         0 1 1 0 0 1 0 1
'l'      108         0 1 1 0 1 1 0 0
'l'      108         0 1 1 0 1 1 0 0
'o'      111         0 1 1 0 1 1 1 1

Todos estos se encuentran en el rango [96, 192) , por lo que c/96se 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.

 n  ?????????????????????????|???????
'h'                          |    01101000
'e'                          |         01100101
'l'                          |              01101100
'l'                          |                   01101100
'o'                          |                        01101111
-----------------------------+--------------------------------
    <------ discarded ------>|???????0101100110011110111101111

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<<7resta 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.


Probablemente debería mencionar que esto depende de la entrada que se codifica en ASCII, antes de profundizar en la explicación.
Toby Speight

2
@TobySpeight No creo que sea común especificar esto. ¿Qué tipo de codificación incompatible ASCII esperaría que utilizara una respuesta C?
Dennis

EBCDIC es la codificación obvia que no es ASCII. C no prescribe ninguna codificación de caracteres en particular (solo que los dígitos decimales deben estar representados por valores consecutivos, en orden).
Toby Speight

el programa anterior se detiene si la secuencia contiene la cadena no ascii "« úá ÷ o "1: o 111 6f 2: ÷ 246 f6 3: á 160 a0 4: ú 163 5:« 174
RosLuP

@RosLuP La especificación de desafío garantiza que la entrada consistirá en caracteres ASCII imprimibles y líneas nuevas.
Dennis

19

Bash, 74 75 103 99 88 82 76 bytes

-10 bytes gracias a @DigitalTrauma!
-11 bytes gracias a @manatwork!
-6 bytes gracias a @Dennis!

IFS=
b=ppcg
while [ ${b/hello} ];do
read -rN1 a
b=${b: -4}$a
echo -n $a
done

Explicación:

IFS=    # making sure we can read whitespace properly
b=ppcg  # set the variable b to some arbitrary 4 letter string

while [ ${b/hello} ]; do  # while the variable b doesn't contain "hello", do the following
    read -rN1 a           # get input
    b=${b: -4}$a          # set b to its last 4 chars + the inputted char
    echo -n $a            # output the inputted char
done

Pruébalo en línea!


2
¡Esto es genial! Esperaba que hubiera una respuesta contundente.

13

Laberinto , 43 41 bytes

Gracias a Sp3000 por guardar 2 bytes.

<_%-742302873844_::%*:*:420#+.:%):,*652_>

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 dehello 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 usamos 0s 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:

_256*,:)%:.+#024:*:*%::_448378203247-%_

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 helloy se repite. Así es como funciona en detalle (recuerde que Labyrinth está basado en la pila):

_256*            Multiply the encoding by 256 in preparation for the next iteration.
,                Read one byte from STDIN.
:)%              Duplicate, increment, modulo. If we hit EOF, then , returns
                 -1, so incrementing and modulo terminates the program due to
                 the attempted division by zero. However, if we did read a
                 character, we've just compute n % (n+1), which is always n itself.
:.               Print a copy of the character we just read.
+                Add it to our encoding (we'll make sure to multiply the
                 encoding by 256 at the end of the iteration, so there's room
                 for our new character).
#024             Push 1024, using the stack depth to push the initial 1.
:*:*             Square it twice. That gives 2^40.
%                Take the encoding modulo 2^40 to truncate it to the last 5
                 characters.
::               Make two copies of the encoding.
_448378203247    Push the value that corresponds to "hello".
-                Subtract it from the encoding, giving zero iff the last 5
                 characters were "hello".
%                Take the other copy of the encoding modulo this value, again
                 terminating if we've reached "hello".
                 The actual value of this modulo - if it didn't terminate the
                 the program - is junk, but we don't really care, we just need
                 any disposable value here for the <...>
_                We push a zero as the second disposable value.

8

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

+
[
  >,.
  >h
  [-<->]
  +<
  [
    >-<[-][in input spot, not h]
  ]
  >
  [
    -
    <
    [in input spot, h has been read]
    ,.
    >e
    [-<->]
    +<
    [
      >-<[-][in input spot, not e]
    ]
    >
    [
      -
      <
      [in input spot, e has been read]
      ,.
      >l
      [-<->]
      +<
      [
        >-<[-][in input spot, not l]
      ]
      >
      [
        -
        <
        [in input spot, l has been read]
        ,.
        >l
        [-<->]
        +<
        [
          >-<[-][in input spot, not l]
        ]
        >
        [
          -
          <
          [in input spot, l has been read]
          ,.
          >o
          [-<->]
          +<
          [
            >-<[-][in input spot, not o]
          ]
          >
          [
            -
            <
            [in input spot, o has been read]
            <->>
          ]
        ]
      ]
    ]
  ]
  <<
]

Esto se ve divertido :)

¡Bienvenido a Programming Puzzles y Code Golf StackExchange!
betseg

1
Este código tiene múltiples problemas, pero el mayor problema es que no incluye la lógica para manejar los casos ahehellobcorrectamente; en medio de una posible coincidencia, solo verifica la siguiente letra helloy no busca una hpara comenzar de nuevo.
Mitch Schwartz

8

Bash , 73 68 66 bytes

IFS=
[[ $1 != olleh ]]&&read -rN1 c&&echo -n $c&&exec $0 $c${1::4}

Asume 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 dodetermina si la condición se cumple.

A continuación, configuramos el separador de campo interno en la cadena vacía (por readlo que no se ahogará en el espacio en blanco), leeremos bytes sin procesar ( -r) de STDIN y los almacenaremos c. $?es el código de salida del comando anterior, por lo que lee exactamente un -N1byte ( ) para una no coincidencia y cero bytes ( -N0). La lectura de cero bytes, ya sea por golpear EOF o porque -N0se especificó, hace readque 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 .


¡Muy bueno de verdad!

8

brainfuck, 117 bytes

--->>>------>>>+>>>+>>>++++<,[.-----<-[>--<-----]<[<<<]>>>[<[<<<+>>>>->+<<-]>[>>
+>]<[+[-<<<]]>>[<+>-]>>]<[[-]<<<,<]>]

Formateado:

--->>>------>>>+>>>+>>>++++
<,
[
  .-----<-[>--<-----]<[<<<]
  >>>
  [
    <[<<<+>>> >->+<<-]
    >[>>+>]
    <[+[-<<<]]
    >>[<+>-]
    >>
  ]
  <[[-]<<<,<]
  >
]

Pruébalo en línea .

Esto inicializa la cinta con los caracteres en hellodesplazamiento 107, 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.


7

Ruby , 46 60 bytes

a="";loop{q=$<.getc;~p if a[-5..-1]=="hello"||!q;a+=q;$><<q}

Prué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:

a = ""
loop {
    q = $<.getc
    ~p if a[-5..-1] == "hello" || !q
    a += q
    $><< q
}

O, más descabellado:

a = ""
loop do
    q = STDIN.getc
    break if a[-5..-1] == "hello" or not q
    a += q
    print q
end

1
acrece cada vez que se lee un personaje. ¿Se bloquea esto si la entrada es infinita?
betseg

@betseg hm, tal vez. Déjame ver si puedo arreglar eso
Conor O'Brien

7

Pitón 3, 120 116 104 Bytes

Funciona con corrientes infinitas, golf por primera vez, cualquier consejo es apreciado.

import sys
a=1
c=''
while(a):
    a=sys.stdin.read(1)
    if a:print(end=a)
    c=(c+a)[-5:]
    if c=='hello':break

Gracias @DJMcMayhem por guardar algunos bytes :)


Bienvenido al sitio! c=[0,c+1]['hello'[c]==a]debería ahorrarte algunos bytes. Además, a=1es más corto también.
DJMcMayhem

2
No necesitas el paréntesis whileen Python.
PurkkaKoodari

6

Haskell, 41 47 43 bytes

f l|w@"hello"<-take 5l=w|a:b<-l=a:f b|1<2=l

La 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!


2
La entrada también puede ser finita, por lo que creo que debe lidiar con el caso cuando llegue al final de la cadena
Leo

@Leo: Vaya, lo perdí por completo. Fijo.
nimi

2
El primer guardia puede ser acortado |w@"hello"<-take 5l=w.
Ørjan Johansen

@ ØrjanJohansen: oh, esa es buena. ¡Gracias!
nimi

6

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 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 ha 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 hnuevo. Inicialmente, esto se debió a que realmente no sabía cómo iba a manejar esto y hes 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 -3si la entrada es e, 0si la entrada es h, 4si la entrada es ly 7si 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 lo 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 ly 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 oy 4 para ly 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 lal final de la pila, pero si es el segundo, debemos empujar un o. ¿Recuerdas que guardamos -3en 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.


Un esfuerzo heroico!

5

C ++, 142 141 bytes

#import<iostream>
void f(std::istream&i){i>>std::noskipws;char c;for(std::string s="     ";s!="hello"&&i>>c;)s.erase(0,1),s+=c,std::cout<<c;}

Pruébalo en línea!


¿Sería esto posible con GCC? No veo #importen los programas de GCC C ++ ...
ckjbgames

1
@ckjbgames #importes una extensión GCC obsoleta.
Steadybox

1
@ckjbgames más información aquí: stackoverflow.com/questions/172262/…
iFreilicht

@iFreilicht Esa pregunta realmente me hizo preguntar eso.
ckjbgames 05 de

1
@ckjbgames es posible que desee echar un vistazo a la segunda respuesta: stackoverflow.com/a/172264/2533467 "La importación en gcc es diferente de la importación en VC ++. Es una forma sencilla de incluir un encabezado como máximo una vez. "
iFreilicht

3

Nodo, 124 bytes

with(process)with(stdin)on('data',d=>[...d].map(c=>(s=(stdout.write(c),s+c).slice(-5))=='hello'&&exit()),setEncoding(),s='')

Sin suponer que la secuencia se ajustará en la memoria disponible.


3

C #, 134 bytes

using C=System.Console;class P{static void Main(){var s="";for(int c;(c=C.Read())>=0&!s.Contains("olleh");C.Write(s[0]))s=(char)c+s;}}

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?)

using C=System.Console;

class P
{
    static void Main()
    {
        var s="";
        for(int c;(c=C.Read())>=0&!s.Contains("olleh");C.Write(s[0]))
            s=(char)c+s;
    }
}

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:

using C=System.Console;class P{static void Main(){var s="     ";for(int c;(c=C.Read())>=0&s!="hello";C.Write(s[4]))s=s.Substring(1)+(char)c;}}

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.

using C=System.Console;

class P
{
    static void Main()
    {
        var s="     ";
        for(int c;(c=C.Read())>=0&s!="hello";C.Write(s[4]))
            s=s.Substring(1)+(char)c;
    }
}

3

PHP, 57 55 53 bytes

while(hello!=$s=substr($s.$c,-5))echo$c=fgetc(STDIN);

Como no hay archivos infinitos, tomo información de STDIN. Corre con -nr.

Recorra la entrada, imprima el carácter actual, añádalo $s, corte $slos últimos 5 caracteres. Romper el ciclo cuando $ses hello.


3

Vim, 39 bytes

:im hello hello:se noma
:map : i

i

Pruébalo en línea!

:im hello                        "Remap 'hello' in insert mode to
          hello                "write hello, then hit escape
                 :se noma       "then set the buffer to not-modifiable
:map : i                        "THEN remap ':' to 'i' so that can't be changed

i                                "enter insert mode and await an infinite stream of input

¿Es este un método de entrada aceptado para Vim? Pensé que los programas de Vim generalmente esperan que la entrada ya esté en el búfer antes de comenzar.
Martin Ender

Para ser sincero, no lo sé. Eso es cierto, pero apenas permite una transmisión infinita, así que lo hice de esta manera sin pensarlo realmente.
nmjcman101

¿Qué sucede si hay un carácter de escape en la secuencia de entrada?
dim

@dim pregunté, y OP especificó solo ASCII imprimible y líneas nuevas. ESC no está incluido en el afaik ASCII imprimible
nmjcman101

3

PowerShell, 111 bytes

Probablemente haya una mejor manera de hacer esto, pero no puedo verla en este momento.

while(($x=($x+$host.UI.RawUI.ReadKey("IncludeKeyDown").character+"     ").substring(1,5)).CompareTo("hello")){}

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.


3

Esquema 115 bytes

(do((c(read-char)(read-char))(i 0(if(eqv? c(string-ref"hello"i))(+ i 1)0)))((or(eof-object? c)(= i 5)))(display c))

Versión legible:

(do ((c (read-char) (read-char))                            ; read stdin
     (i 0 (if (eqv? c (string-ref "hello" i)) (+ i 1) 0)))  ; check target
    ((or (eof-object? c) (= i 5))) ; finish if end of stdin, or word found
  (display c))                     ; display each character

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.


Buena respuesta, bienvenido al sitio!
DJMcMayhem

3

AWK, 95 bytes

BEGIN{RS="(.)"
split("hello",h,"")}{for(j=0;++j<6;){c=RT
printf c
if(c!=h[j])next
getline}exit}

Hay 2 cosas que aprendí aquí:
1) Para dividir registros entre caracteres, use RS="(.)"y luego RTdebe usarse en lugar de $1
2) ORSes usado por printy está predeterminado en "\n"
3) No puedo contar hasta 2 y el uso printfes "más barato" que asignarORS y utilizandoprint

Ejemplo de uso: colocar el código en ARCHIVO

awk -f FILE some_data_file

o

some process | awk -f FILE

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 BEGINbloque a través de:

awk -v RS='(.)'

¡Una solución realmente complicada! (Tal vez porque es viernes por la tarde, pero me parece buena entrada para el desafío ofuscado también.) Aunque me gustaría probar un enfoque más awkish: BEGIN{RS="(.)"}{printf RT}"olleh"==a=RT substr(a,1,4){exit}.
manatwork

Por extraño que parezca, tengo una respuesta casi exacta lista para enviar hace una hora ... y olvidé enviarla. : p
Robert Benson

3

Python 3 (Linux), 73 72 bytes

s=c='_';I=open(0)
while'olleh'!=s>''<c:c=I.read(1);s=c+s[print(end=c):4]

¡Gracias a @MitchSchwartz por jugar golf en 1 byte!

Pruébalo en línea!


No entiendo. ¿Cómo se whileevalúa la condición para evaluar adecuadamente? Parece que estás comparando un booleano con una cadena vacía.
iFreilicht

1
s[print(end=c):4]guarda un byte
Mitch Schwartz

1
@iFreilicht Python analiza condicionales encadenados como lo haría en matemáticas ( a <b <c , por ejemplo). La condición es una abreviatura de '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.
Dennis

@MitchSchwartz Eso sí. ¡Gracias!
Dennis

3

Código de máquina 8086, 22 bytes

00000000  bf 11 01 b4 01 cd 21 ae  75 f6 81 ff 16 01 72 f3  |......!.u.....r.|
00000010  c3 68 65 6c 6c 6f                                 |.hello|
00000016

Código de ensamblaje equivalente:

org 0x100
use16
a:  mov di, msg
b:  mov ah, 1       ; read one byte from stdin with echo
    int 0x21        ; dos syscall -> result in AL
    scasb           ; if (DI++ == AL)
    jne a
    cmp di, msg+5
    jb b
    ret
msg db "hello"

¿Como funciona?

1
Agregué el código de ensamblaje equivalente. Básicamente se basa en un syscall de DOS muy útil, que lee un byte de stdin y lo devuelve a stdout al mismo tiempo. El 8086 también tiene una instrucción de comparación de cadenas de un solo byte que es útil aquí.
user5434231

2

Pyth, 49 47 bytes

Wn"hello"=>5+kp$__import__("sys").stdin.read(1)

Pyth 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 caracteres ky 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.


2

Lua, 68 64 bytes

l=""while l~="hello"do c=io.read(1)io.write(c)l=l:sub(-4)..c end

1
Cambie el corte a l:sub(-4), luego puede reducir la inicialización de l="".
manatwork 05 de

@manatwork Eso está bien. Gracias por el consejo.
Blab

2

Ruby, 59 49 48 43 bytes

Ahora sin despotricar, más corto y sin pérdida de memoria.

s=''
s=$>.putc$<.getc+s[0,4]until'olleh'==s

Ahorró 5 bytes al eliminar algunos paréntesis y un espacio gracias a Dennis



1

röda , 49 47 bytes

{a=[0]*5{|x|[x];a=a[1:]+x;z if[a&""="hello"]}_}

Prué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:

{
    a=[0]*5                /* Initialize the array with 5 zeroes. */
    {|x|                   /* For each x in the input stream: */
        [x];               /* Print x */
        a=a[1:]+x;         /* Add x and remove the sixth last character. */
        z if[a&""="hello"] /* If "hello" is found, crash the program */
                           /* with an undefined variable. */
    }_                     /* End for loop. */
}

¿Dónde está la documentación de Roda?
ckjbgames

@ckjbgames Aquí. Uso la última versión 0.12, que está en su propia sucursal en Github.
fergusq

1

Java 7, 122 118 124 123 150 141 bytes

void c()throws Exception{String a="aaaaa";for(int b;!a.equals("hello")&(b=System.in.read())>=0;a=a.substring(1)+(char)b)System.out.write(b);}

Ahora se detiene cuando se alcanza el final de la secuencia. Ahora maneja la entrada infinita sin quedarse sin memoria.


Apuesto a que esto no puede manejar la entrada infinita.
Titus

@Titus arreglado ...
Poke

Voté a favor sin ver que writese usara en lugar de print. No puedo deshacer mi voto negativo, lo siento :(
Olivier Grégoire

1

Ruby, 51 bytes

x="";$><<x[-1]while/hello./!~x=x[/.{0,5}$/]+$<.getc
  • No espera nuevas líneas
  • Funciona con entrada infinita.

1

AHK , 116 bytes

Loop,Read,%1%
{a=%A_LoopReadLine%`n
Loop,Parse,a
{Send % c:=A_LoopField
If((f:=c SubStr(f,1,4))=="olleh")
ExitApp
}}

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.


1

Mathematica, 107 bytes

i="";EventHandler[Dynamic@i,"KeyDown":>(i=i<>CurrentValue@"EventKey";If[StringTake[i,-5]=="hello",Exit[]])]

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.


1

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

Set up the buffers with helo
This is done Naively; sue me
>++++++++[<+++++++++++++>-]     h
>++++++++++[<++++++++++>-]<+>   e
>+++++++++[<++++++++++++>-]     l
>++++++++++[<+++++++++++>-]<+>  o

THE MAIN LOOP
+
[ matches o
    [ matches l
        [ matches l
            [ matches e
                [ matches h
                    ,. Read a character and immediently write it
                    <<<<[->>>>->+<<<<<] Subtract it from h
                    >>>>>[-<<<<<+>>>>>] Correct the h
                    < Terminate this part of the loop if it matches h
                ]
                ,. Same as above
                <<<[->>>->+<<<<] Subtract it from e
                >>>>[-<<<<+>>>>] Correct the e
                < Terminate this part of the loop if it matches e
            ]
            ,. Same as above
            <<[->>->+<<<] Subtract it from l
            >>>[-<<<+>>>] Correct the l
            < Terminate this part of the loop if it matches l
        ]
        ,. Same as above
        <<[->>->+<<<] Subtract it from l
        >>>[-<<<+>>>] Correct the l
        < Terminate this part of the loop if it matches l
    ]
    ,. Same as above
    <[->->+<<] Subtract it from o
    >>[-<<+>>] Correct the o
    < Terminate this part of the loop if it matches o
]

Pruébalo en línea!


Lo iba a hacer así, pero luego me di cuenta de que esto genera el byte cero infinitamente para la entrada que no contiene "hola": tio.run/nexus/…
KarlKastor

Esto también falla en ahehellob.
Mitch Schwartz
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.