Mi avevi ciao


30

Compito

Leggi in un flusso o file di testo possibilmente infinito, producendo i suoi contenuti fino a quando la parola non helloviene emessa, rispettando le seguenti regole.

  • Una volta che helloè stato emesso, il codice dovrebbe essere chiuso immediatamente. Ad esempio, non dovrebbe aspettare una nuova riga.

  • Il tuo codice dovrebbe essere visualizzato come va. Cioè non dovrebbe leggere in una grande quantità di input e quindi iniziare a produrre.

  • Se il flusso / file non contiene hello, il tuo codice dovrebbe continuare a inviare l'input per sempre o fino al raggiungimento della fine del flusso / file.

  • Questa è una sfida sensibile al maiuscolo / minuscolo, quindi hellonon è uguale a Hello.

  • Si può presumere che l'input sia costituito esclusivamente da caratteri ASCII e newline stampabili.

  • Il tuo codice non può aspettarsi che il testo venga terminato da una nuova riga o che ci siano delle nuove righe nell'input. Inoltre, il codice non può presumere che verrà eseguito su una macchina con una quantità infinita di memoria.

  • Puoi presumere che il tuo codice verrà chiamato da una directory vuota.

Esempio di flusso di input

I once had a horse called hellopina.

Produzione

I once had a horse called hello

Mancia

Esegui yes | tr -d \\n | <your program>per verificare se funziona con flussi infiniti. Se non stampa nulla e / o perde memoria, il programma non è conforme alle specifiche. Dovrebbe stampare yyyyyyyyyyyyyyyyyyyyyy...per sempre senza nuove righe.


1
Ci è permesso leggere qualcosa dopo il "ciao"? La domanda sembra vietare qualsiasi lettura aggiuntiva, che potrebbe essere problematica in linguaggi come (Standard) C, che forniscono input bufferizzati con read-ahead automatico.
Toby Speight,

Probabilmente dovresti cambiare la risposta accettata all'assembly, poiché è più corta di 2 byte.
Rɪᴋᴇʀ

@Riker Sarebbe bello se qualcuno potesse testarlo o almeno dire di credere che funzioni prima.

Risposte:


2

Gelatina , 24 byte

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

Provalo online!

Spiegazione:

ṫ-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 byte

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

Provalo online!

Come funziona

Questo è un programma completo. Definiamo una funzione f per i nostri scopi. Per salvare i byte, viene dichiarato con due argomenti che l'impostazione predefinita è int . Questo è un comportamento indefinito, ma in pratica, n verrà inizializzato come 1 quando si esegue il programma senza argomenti aggiuntivi, c conterrà i 32 bit inferiori del puntatore al vettore argomento

Mentre la condizione

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

tiene, eseguiremo il corpo del ciclo while :

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

Per comprendere appieno la condizione, dobbiamo prima esaminare il corpo. Per ora, tutto ciò che osserviamo è che c=getchar()legge un singolo byte da STDIN (se possibile) e lo memorizza nella variabile c .

La sequenza di byte ciao appare come segue in diverse rappresentazioni.

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

Tutti questi rientrano nell'intervallo [96, 192) , quindi c/96valuteranno 1 per ciascuno di questi byte e 0 per tutti i caratteri ASCII rimanenti. In questo modo, putchar(c)/96*c( putchar stampe e restituisce il suo argomento) valuterà a c se c è `, una lettera minuscola, uno dei {|}~, o di carattere DEL; per tutti gli altri caratteri ASCII, verrà valutato su 0 .

n viene aggiornato spostandolo di cinque bit a sinistra, quindi XOR il risultato con il risultato del paragrafo precedente. Poiché un int ha una larghezza di 32 bit (o almeno così assumiamo in questa risposta), alcuni dei bit spostati potrebbero "cadere da sinistra" (l'overflow di numeri interi con segno è un comportamento indefinito, ma gcc si comporta come l'istruzione x64 che genera qui). Iniziando con un valore sconosciuto di n , dopo averlo aggiornato per tutti i caratteri di ciao , otteniamo il seguente risultato.

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

Si noti che i 25 bit inferiori formano l'intero 0xb33def , che è la costante magica nella condizione. Mentre v'è una certa sovrapposizione tra i bit dei due byte adiacenti, mappatura byte sotto 96 a 0 fa in modo che non ci siano falsi positivi.

La condizione è composta da due parti:

  • ~(getchar()) prende il bit bit NOT del risultato della lettura (o del tentativo di leggere) un byte da STDIN.

    Se getchar ha esito positivo, restituirà il valore del byte letto come int . Poiché l'ingresso è costituito interamente da caratteri ASCII, il byte di lettura può avere solo i suoi 7 bit più bassi impostati, quindi in questo caso NOT avrà i suoi 25 bit più alti impostati.

    Se getchar fallisce (non più input), restituirà -1 e il bit a bit NOT sarà 0 .

  • n-0xb33def<<7sottrae la costante magica da prima da n , quindi sposta il risultato di 7 unità a sinistra.

    Se gli ultimi 5 byte letti fossero ciao , i 25 bit più bassi di n saranno pari a 0xb33def e la sottrazione li azzererà. Lo spostamento della differenza produrrà 0 poiché i 7 bit più alti "cadranno da sinistra".

    D'altra parte, se gli ultimi 5 byte letti non fossero ciao , verrà impostato uno dei 25 bit più bassi della differenza; dopo lo spostamento, sarà uno dei 25 bit più alti .

Infine, se getchar ha avuto successo e non abbiamo ancora stampato ciao , verrà impostato AND bit per bit, tutti i 25 bit più alti dell'operando di sinistra e almeno uno dei 25 bit più alti di quello di destra. In questo modo, &produrrà un numero intero diverso da zero e il ciclo continua.

D'altra parte, se l'input è esaurito o abbiamo già stampato ciao , uno degli operandi AND bit per bit sarà zero, e così sarà il risultato. In questo caso, usciamo dal ciclo e il programma termina.


Probabilmente dovresti menzionare che questo dipende dall'input codificato in ASCII, prima di approfondire la spiegazione.
Toby Speight,

2
@TobySpeight Non credo sia comune specificarlo. Che tipo di codifica ASCII incompatibile ti aspetteresti di utilizzare una risposta C?
Dennis,

EBCDIC è l'ovvia codifica che non è ASCII. C non prescrive una particolare codifica dei caratteri (solo che le cifre decimali devono essere rappresentate da valori consecutivi, in ordine).
Toby Speight,

il programma sopra si interrompe se il flusso contiene la stringa non ascii "« úá ÷ o "1: o 111 6f 2: ÷ 246 f6 3: á 160 a0 4: ú 163 5:« 174
RosLuP

@RosLuP Le specifiche della sfida garantiscono che l'input sarà composto da caratteri ASCII stampabili e nuove righe.
Dennis,

19

Bash, 74 75 103 99 88 82 76 byte

-10 byte grazie a @DigitalTrauma!
-11 byte grazie a @manatwork!
-6 byte grazie a @Dennis!

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

Spiegazione:

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

Provalo online!


2
Questo è fantastico! Speravo ci sarebbe stata una risposta bash.

13

Labyrinth , 43 41 byte

Grazie a Sp3000 per aver salvato 2 byte.

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

Provalo online!

Spiegazione

L'idea di base è di codificare gli ultimi cinque caratteri nella base 256 in un unico numero intero. Quando arriva un nuovo personaggio, possiamo "accodarlo" moltiplicando il numero intero per 256 e aggiungendo il nuovo punto di codice. Se vogliamo esaminare solo gli ultimi 5 caratteri, prendiamo il valore modulo 256 5 = 2 40 = 1099511627776. Quindi possiamo semplicemente verificare se questo valore è uguale a 448378203247, che è quello che otteniamo quando trattiamo i punti di codice dihello come base-256 cifre.

Per quanto riguarda il codice ... <...>è un po 'un idioma del labirinto. Ti permette di scrivere un ciclo infinito senza alcun flusso di controllo condizionale su una singola riga, risparmiando molti byte su spazi e avanzamenti di riga. La condizione principale perché questo funzioni è che ci sono due valori usa e getta sopra lo stack quando raggiungiamo il <(normalmente usiamo 0s per quello, ma il valore effettivo è arbitrario).

Naturalmente, il programma ha bisogno di una logica condizionale per capire quando terminare. Ma terminare in modo condizionale il programma è possibile dividendolo per un valore che è zero quando vogliamo che il programma finisca. Il <...>costrutto funziona spostando l'intera riga a sinistra (ciclicamente) quando l'IP si trova all'estremità sinistra e quindi spostandola immediatamente in posizione. Ciò significa che il codice viene effettivamente eseguito da destra a sinistra. Invertiamolo:

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

Questa è un'iterazione del ciclo che legge un personaggio, termina se abbiamo raggiunto EOF, stampa il personaggio, lo aggiunge alla nostra codifica, lo tronca a 5 caratteri, verifica l'uguaglianza helloe si ripete. Ecco come funziona in dettaglio (ricorda che Labyrinth è basato su stack):

_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 byte

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

Più di 500 byte sono nelle costanti che devo golf un po '.

Essenzialmente è una macchina a stati, quindi l'input infinito non è un problema.

Questa è la versione leggermente commentata

+
[
  >,.
  >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]
            <->>
          ]
        ]
      ]
    ]
  ]
  <<
]

Sembra divertente :)

Benvenuto in Puzzle di programmazione e Code Golf StackExchange!
Betseg,

1
Questo codice ha più problemi, ma il problema maggiore è che non include la logica per gestire i casi in modo ahehellobcorretto; nel mezzo di una potenziale corrispondenza, controlla solo la lettera successiva helloe non cerca un nuovo hinizio.
Mitch Schwartz,

8

Bash , 73 68 66 byte

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

Presuppone una directory con nessun o solo file nascosto. Deve essere eseguito come <path/to/script>.

Provalo online!

Come funziona (obsoleto)

All'inizio del ciclo while , per prima cosa testiamo se la stringa nella variabile s (inizialmente vuota) è uguale a olleh ( ciao all'indietro, olé) ​​e restituiamo di conseguenza 0 (corrispondenza) o 1 (non una corrispondenza). Sebbene formalmente parte della condizione del ciclo, il risultato non influirà da solo, poiché solo l'ultimo comando dodetermina se la condizione è valida.

Successivamente, impostiamo il separatore di campo interno sulla stringa vuota (quindi readnon si strozzerà con gli spazi bianchi), leggiamo i byte grezzi ( -r) da STDIN e li memorizziamo in c. $?è il codice di uscita del comando precedente, quindi legge esattamente un ( -N1) byte per una non corrispondenza e zero byte ( -N0). La lettura di zero byte, sia dovuta al colpire EOF sia perché è -N0stata specificata, provoca readl'uscita con il codice di stato 1 , quindi il ciclo while termina; in caso contrario, il corpo viene eseguito e ricominciamo da capo.

Nel corpo, prima stampiamo il byte che leggiamo, quindi aggiorniamo s con s=$c${s::4}. Questo antepone il byte letto a (fino a) i primi quattro byte in s , quindi s sarà uguale a olleh una volta stampato ciao .


Davvero molto bello!

8

Brainfuck, 117 byte

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

formattato:

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

Provalo online .

Questo inizializza il nastro con i caratteri in hellooffset di 107, distanziati di un valore ogni tre celle, quindi tiene traccia degli ultimi cinque caratteri visti e verifica una corrispondenza con ogni nuovo carattere elaborato, utilizzando un flag a destra della stringa per tenere traccia della presenza di una corrispondenza.


7

Rubino , 46 60 byte

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

Provalo online!

Legge i caratteri dallo stdin fino agli ultimi 5 hello, quindi genera la stringa (o fino a quando non rimangono caratteri nello stdin). Termina con errore.

Equivalente a:

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

O, più ungolfed:

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

1
acresce ogni volta che viene letto un carattere. Questo si blocca se l'input è infinito?
Betseg,

@betseg hm, forse. Fammi vedere se riesco a risolvere il problema
Conor O'Brien,

7

Python 3, 120 116 104 byte

Funziona con flussi infiniti, la prima volta giocando a golf, tutti i suggerimenti sono apprezzati.

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

Grazie @DJMcMayhem per aver salvato alcuni byte :)


Benvenuti nel sito! c=[0,c+1]['hello'[c]==a]dovrebbe salvarti alcuni byte. Inoltre, a=1è anche più corto.
DJMcMayhem

2
Non è necessaria la parentesi per whilein Python.
PurkkaKoodari,

6

Haskell, 41 47 43 byte

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

La pigrizia di Haskell gestisce bene l'infinito input / output.

Provalo online!

Modifica: non ha gestito input finiti - risolto. Grazie @Leo per la segnalazione.

Modifica II: @ Ørjan Johansen ha salvato 4 byte. Grazie!


2
L'input potrebbe anche essere finito, quindi penso che dovrai affrontare il caso quando raggiungi la fine della stringa
Leo

@Leo: Oops, ci siamo persi del tutto. Fisso.
nimi,

2
La prima guardia può essere accorciata |w@"hello"<-take 5l=w.
Ørjan Johansen,

@ ØrjanJohansen: oh, è carino. Grazie!
nimi,

6

Cubix, 94 83 82 79 63 56 byte

p>q'-?w.uh'e@U7.'hqi?oqB-!ul.-..$WWu_q<o'\;>....6t?.../!@

Allargato:

        p > q '
        - ? w .
        u h ' e
        @ U 7 .
' h q i ? o q B - ! u l . - . .
$ W W u _ q < o ' \ ; > . . . .
6 t ? . . . / ! @ . . . . . . .
. . . . . . . . . . . . . . . .
        . . . .
        . . . .
        . . . .
        . . . .

Gli appunti

  • L'interprete disabilita il campo di input all'avvio del programma. Pertanto, un flusso infinito di input è impossibile. Questo programma accetta l'input carattere per carattere, quindi se non fosse per questa limitazione, funzionerebbe correttamente.
  • Questo programma non cancella lo stack e diventa molto disordinato. Dal momento che la macchina su cui apparentemente sarà in grado di fornire flussi di input infiniti, sembra ragionevole supporre che abbia anche una memoria infinita.
  • Qualsiasi aiuto sul golf è molto apprezzato.

Provalo online

Puoi provare il programma qui .

Spiegazione

Idea generale

L'idea generale è che vogliamo leggere un personaggio e quindi confrontarlo con vari personaggi (prima h, poi e, poi lecc.). Per tenere traccia del personaggio che abbiamo perso, lo teniamo in fondo alla pila. Quando ne abbiamo bisogno, possiamo facilmente riportarlo in cima.

Ciclo di lettura / scrittura

Il ciclo di lettura-scrittura è semplicemente la quinta riga. Tutti i caratteri non utilizzati vengono sostituiti da no-ops ( .):

        . . . .
        . . . .
        . . . .
        @ . . .
' h q i ? o q B - ! u l . - . .
. . . . _ . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
        . . . .
        . . . .
        . . . .
        . . . .

Questo può essere suddiviso in due parti: lettura e (scrittura e controllo). La prima parte contiene le istruzioni fino al punto di domanda incluso. La seconda parte è il resto della linea. Dato che questo circola in giro, supponiamo di iniziare con una pila di[...]

    @
'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 seconda parte (scrittura e controllo) è di nuovo lineare. Lo stack inizia come [next-char, ..., input]. Abbiamo estratto il personaggio successivo, perché questo cambia più avanti nel programma.

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.

Ora, l'IP ricomincerà all'inizio di questo ciclo, ripristinando il carattere successivo da controllare h.

Abbinando il personaggio successivo

Se l'IP ha effettuato un'inversione di marcia (ovvero il carattere che abbiamo letto e stampato corrisponde al carattere successivo 'hello'), dobbiamo controllare quale carattere era l'input e, a seconda di ciò, spingere il carattere successivo in fondo alla pila. Dopodiché, dobbiamo tornare al ciclo di lettura / scrittura, senza spingere hnello stack, quindi abbiamo bisogno di un altro modo per arrivarci.

Per prima cosa: determinare quale carattere era l'input. Lo stack è simile al seguente: [..., prev-char, input, 0].

        . . . .
        - ? . .
        u h ' e
        . . . .
. . . . . . . . . ! u . . . . .
. . . . . . . . . \ ; . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
        . . . .
        . . . .
        . . . .
        . . . .

Per confrontare l'input, utilizziamo hnuovamente il codice carattere . Inizialmente, questo perché non sapevo davvero come avrei gestito questo ed hè il primo personaggio della stringa da controllare, ma alla fine è stato abbastanza conveniente. Se sottraggiamo il codice carattere di h dall'input, otteniamo -3se l'input è e, 0se l'input è h, 4se l'input è le 7se l'input è o.

Questo è utile, perché il ?comando ci consente di separare facilmente i valori negativi da valori positivi e zero. Pertanto, se l'IP gira a sinistra, la differenza era negativa, quindi l'input era e, quindi il carattere successivo dovrebbe essere un l. Se l'IP continua ad andare dritto, la differenza era 0, quindi l'input era h, quindi il carattere successivo dovrebbe essere un e. Se l'ingresso è un lo un o, l'IP gira a destra.

Tutte le istruzioni eseguite prima del punto interrogativo sopra menzionato sono:

;!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]

Ora l'IP cambia direzione come descritto sopra. Esaminiamo le diverse possibilità.

Ingresso 'e'

Per prima cosa considereremo l'input e, che fa spostare l'IP verso l'alto dal ?, poiché la differenza è 3. Tutti i caratteri irrilevanti sono stati rimossi dal cubo.

        . > q '
        . ? . .
        . . . .
        . . . .
. . q . . . . . . . . l . . . .
$ W W . . . . . . . . > . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
        . . . .
        . . . .
        . . . .
        . . . .

I caratteri vengono eseguiti in questo ordine (esclusi alcuni caratteri del flusso di controllo):

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, ...]

Ora l'IP ha raggiunto nuovamente il ciclo di lettura / scrittura.

Ingresso 'h'

Se l'ingresso era 'h', la differenza è 0, quindi l'IP non cambia direzione. Ecco di nuovo il cubo, con tutti i personaggi irrilevanti rimossi. Poiché questo percorso include alcune no-op, tutte le no-op che passa sono state sostituite &. L'IP inizia dal punto interrogativo.

        . . . .
        . ? w .
        . . ' e
        . . . .
. . . . . . . . . ! . . . . . .
. . . u _ q < . . \ . . . . . .
. . ? & & & / . . & . . . . . .
. . & . . . . . . & . . . . . .
        . . . .
        & & & &
        . . . .
        . . . .

Le istruzioni eseguite sono:

'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

E ora stiamo entrando di nuovo nel ciclo di lettura / scrittura, quindi abbiamo finito.

Altri input

Tutti gli altri input producono una differenza positiva, quindi l'IP gira a destra al punto interrogativo. Dobbiamo ancora separare il le il o, quindi è quello che faremo dopo.

Separare il 'l'e'o'

Tieni presente che la differenza è 7 per oe 4 per le che dobbiamo terminare il programma se l'ingresso era un o. Ecco di nuovo il cubo con le parti irrilevanti sostituite da una .e le no-op che l'IP attraversa sono state sostituite da e commerciali.

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

Discernere tra i due 'l's

Quindi, ora sappiamo che l'input è stato un l, ma non sappiamo quale l. Se è il primo, dobbiamo spingerne un altro lin fondo alla pila, ma se è il secondo, dobbiamo spingere un o. Ricordi che abbiamo salvato -3in fondo alla pila appena prima di spingere il primo l? Possiamo usarlo per separare i due rami.

        . . . .
        . . . .
        . . . .
        . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
6 t ? . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
        . . . .
        . . . . 
        . . . .
        . . . .

Lo stack inizia come [..., -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

Primo 'l'

Se questo è stato il primo 'l', dobbiamo spingerne un altro 'l'. Per salvare i byte, utilizziamo gli stessi caratteri del primo 'l'. Possiamo semplificare lo stack a [...]. Ecco la parte rilevante del cubo, senza operazioni di sostituzione sostituite da e commerciali.

        p > q '
        . . . .
        . . . .
        . . . .
' . q . . . . . . . . l . . . .
$ W W . . . . . . . . > & & & &
. . ? . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
        . . . .
        . . . .
        . . . .
        . . . .

Vengono eseguite le seguenti istruzioni:

$'pq'lq
$'          no-op
  pq        no-op
    'l      Push the character code of l
            Stack: [..., 108]
      q     Send it to the bottom
            Stack: [108, ...]

Stiamo per entrare nel ciclo di lettura / scrittura, quindi abbiamo finito con questo ramo.

Secondo 'l'

Se l'ingresso era il secondo 'l'in 'hello', l'IP girava a destra al punto interrogativo. Ancora una volta, possiamo semplificare lo stack [...]e l'IP inizia a ?, puntando verso sud questa volta.

        . . . .
        . . . .
        . . . .
        . . . .
. . . . . . . . . . . . . . . .
. . . u _ q < o ' \ . . . . . .
. . ? . . . . . . & . . . . . .
. . & . . . . . . & . . . . . .
        . . . .
        & & & &
        . . . .
        . . . .

Le istruzioni eseguite sono:

'oq_
'o          Push the character code of 'o'
            Stack: [..., 111]
  q         Move the top item to the bottom
            Stack: [111, ...]
   _        No-op

E l'IP sta per entrare di nuovo nel ciclo di lettura / scrittura, quindi abbiamo finito anche con questo ramo.


Uno sforzo eroico!

5

C ++, 142 141 byte

#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;}

Provalo online!


Questo sarebbe possibile con GCC? Non vedo #importnei programmi GCC C ++ ...
ckjbgames

1
@ckjbgames #importè un'estensione GCC obsoleta.
Steadybox

1
@ckjbgames maggiori informazioni qui: stackoverflow.com/questions/172262/...
iFreilicht

@iFreilicht Questa domanda mi ha fatto fare questa domanda.
ckjbgames,

1
@ckjbgames potresti dare un'occhiata alla seconda risposta: stackoverflow.com/a/172264/2533467 "L'importazione in gcc è diversa dall'importazione in VC ++. È un modo semplice per includere un'intestazione al massimo una sola volta. "
iFreilicht,

3

Nodo, 124 byte

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

Non dare per scontato che il flusso si adatti alla memoria disponibile.


3

C #, 134 byte

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;}}

Provalo online

Legge un personaggio, controlla che non sia -1 (EOS) e che non abbiamo ancora visto "ciao", quindi lo antepone a una stringa e scrive il carattere. Anticipiamo perché s[0]è molto più breve di (char)s. Questo ha un costo quadratico nella lunghezza della stringa, poiché deve allocare e scansionare l'intero input ogni volta che legge un carattere (questo si arresterà in modo anomalo dopo 2 GB di input a causa di vincoli nel CLR, è consentito?)

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;
    }
}

Per una versione (più lunga: 142 byte) che non esaurisce la memoria e che ha un costo per carattere costante, vedere di seguito:

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;}}

Questo mantiene gli ultimi 5 caratteri in una stringa di 5 lunghezze, il che significa brevi confronti e una ricerca dell'ultimo carattere economica, ma è notevolmente più costoso da aggiornare.

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 byte

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

poiché non ci sono file infiniti, prendo l'input da STDIN. Corri con -nr.

Passa attraverso l'input, stampa il carattere corrente, aggiungilo a $s, taglia $sgli ultimi 5 caratteri. Interrompere il ciclo quando lo $sè hello.


3

Vim, 39 byte

:im hello hello:se noma
:map : i

i

Provalo online!

: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

È un metodo di input accettato per Vim? Pensavo che i programmi Vim di solito prevedessero che l'input fosse già nel buffer prima di iniziare.
Martin Ender,

Ad essere sincero, non lo so? Questo è vero, ma difficilmente consente un flusso infinito, quindi l'ho fatto in questo modo senza pensarci tanto.
nmjcman101

Cosa succede se è presente un carattere di escape nel flusso di input?
fioco

@dim ho chiesto e OP ha specificato solo ASCII e newline stampabili. ESC non è incluso in ASCII stampabile
afaik

3

PowerShell, 111 byte

Probabilmente esiste un modo migliore per farlo, ma al momento non riesco a vederlo.

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

Questo legge i tasti premuti senza sopprimere l'eco. Il personaggio viene aggiunto a $ x che viene tagliato agli ultimi 5 caratteri e confrontato con "ciao". Questo continua fino a quando il confronto è vero.

Nota: questo non funziona in PowerShell ISE. ReadKey è disabilitato in quell'ambiente.


3

Schema 115 byte

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

Versione leggibile:

(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

Questo prende ogni singolo carattere da stdin ogni volta attorno al loop e segna la sua posizione sulla parola target quando incontra i caratteri di "ciao".

Si interrompe quando si esaurisce l'ingresso o viene visualizzato "ciao". Nessuna memoria utilizzata su un flusso infinito.


Bella risposta, benvenuta nel sito!
DJMcMayhem

3

AWK, 95 byte

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

Ci sono 2 cose che ho imparato qui:
1) Per dividere i record tra i personaggi usare RS="(.)"e quindi RTdeve essere usato invece di $1
2) ORSè usato da printed è impostato di default su "\n"
3) Non posso contare su 2 e usare printfè "più economico" che assegnare ORSe utilizzandoprint

Esempio di utilizzo: inserire il codice in FILE

awk -f FILE some_data_file

o

some process | awk -f FILE

Il codice è stato testato usando il yes | ...suggerimento di Dennis e ho visto un sacco di messaggi y.

Cordiali saluti, è possibile eseguire l'assegnazione RS come opzione ed estrarlo dal BEGINblocco tramite:

awk -v RS='(.)'

Soluzione davvero complicata! (Forse perché è Venerdì pomeriggio, ma trovo buona entrata per la sfida offuscato anche.) Anche se vorrei provare un approccio più awkish: BEGIN{RS="(.)"}{printf RT}"olleh"==a=RT substr(a,1,4){exit}.
arte

Stranamente, ho quasi esattamente una risposta pronta a presentare un'ora fa ... e ho dimenticato di inviarlo. : p
Robert Benson,

3

Python 3 (Linux), 73 72 byte

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

Grazie a @MitchSchwartz per giocare a golf a 1 byte!

Provalo online!


Non capisco. Come whilevaluta correttamente la condizione ? Sembra che tu stia confrontando un valore booleano con una stringa vuota.
iFreilicht,

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

1
@iFreilicht Python analizza i condizionali concatenati come si farebbe in matematica ( a <b <c , per esempio). La condizione è una scorciatoia per 'olleh'!=s and s>''and''<c). Non è necessario il test intermedio, ma concatenarli è più breve di quello diretto 'olleh'!=s and''<c.
Dennis,

@MitchSchwartz Che lo fa. Grazie!
Dennis,

3

8086 codice macchina, 22 byte

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

Codice assembly 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"

Come funziona?

1
Ho aggiunto il codice assembly equivalente. Fondamentalmente si basa su un syscall DOS molto utile, che legge un byte dallo stdin e lo riporta allo stdout allo stesso tempo. L'8086 ha anche un'istruzione di confronto di stringhe a byte singolo che è utile qui.
user5434231,

2

Pyth, 49 47 byte

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

Pyth non è molto bravo a prendere un singolo carattere di input. Tutto dentro lo $__import__("sys").stdin.read(1)sta semplicemente facendo. Inoltre, significa che questo funziona solo offline.

Tutto il resto è breve ...

Il programma è un ciclo while senza corpo. All'interno della condizione, il programma legge un carattere, lo stampa di nuovo, aggiunge quel carattere a k(che inizialmente è la stringa vuota), ritaglia tutti tranne gli ultimi 5 caratteri ke quindi verifica che il risultato non lo sia "hello".

32 caratteri ottengono un byte di input, 15 caratteri fanno il resto.

Testato su Linux, funziona anche senza newline, input infinito, ecc.


2

Lua, 68 64 byte

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

1
Modificare lo slicing in l:sub(-4), quindi è possibile ridurre l'inizializzazione di l="".
arte

@manatwork È pulito. Grazie per il consiglio.
Blab,

2

Rubino, 59 49 48 43 byte

Ora libero, più corto e senza perdita di memoria.

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

Hai salvato 5 byte eliminando alcune parentesi e uno spazio grazie a Dennis



1

Röda , 49 47 byte

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

Provalo online!

Questa è una funzione anonima che legge i caratteri dal suo flusso di input e li emette fino a quando non viene trovato "ciao". Utilizza l'array aper tenere traccia degli ultimi caratteri.

Produce un po 'di spazzatura su STDERR, ma ho capito che è permesso .

Spiegazione:

{
    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. */
}

Dov'è la documentazione di Roda?
ckjbgames

@ckjbgames Qui. Uso l'ultima versione 0.12, che si trova nel suo ramo in Github.
Fergusq,

1

Java 7, 122 118 124 123 150 141 byte

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);}

Ora si interrompe quando viene raggiunta la fine del flusso. Ora gestisce l'input infinito senza esaurire la memoria.


Scommetto che non è possibile gestire input infiniti.
Tito

@Titus fisso ...
Poke

Ho effettuato il downgrade senza vedere writeinvece di essere utilizzato print. Non posso annullare il mio downvote, mi dispiace per questo :(
Olivier Grégoire,

1

Rubino, 51 byte

x="";$><<x[-1]while/hello./!~x=x[/.{0,5}$/]+$<.getc
  • Non si aspetta newline
  • Funziona con input infiniti

1

AHK , 116 byte

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

Non c'è niente di intelligente o magico lì dentro, davvero. La variabile %1%è il primo argomento passato e dovrebbe essere un percorso di file con il flusso. Il file deve essere salvato man mano che viene aggiornato, ma il codice verrà letto fino alla fine anche se si espande dopo l'inizio della lettura.


1

Mathematica, 107 byte

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

L'output diventa un campo in cui l'utente può digitare infinitamente il testo (comprese le nuove righe) fino a quando gli ultimi 5 caratteri sono uguali "hello"; a quel punto, esce.


1

Brainfuck , 281 byte

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

Non sono sicuro del perché, ma sentivo che Brainfuck era la cosa giusta per farlo. Non richiede memoria infinita e può essere riprodotto per sempre.

spiegato

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
]

Provalo online!


Lo avrei fatto in questo modo, ma poi mi sono reso conto che questo emette infinitamente il byte zero per input che non contiene "ciao": tio.run/nexus/…
KarlKastor

Anche questo fallisce ahehellob.
Mitch Schwartz
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.