Vous me avez eu à bonjour

30

Tâche

Lisez un flux de texte ou un fichier éventuellement infini, en affichant son contenu jusqu'à ce que le mot hellosoit sorti, en respectant les règles suivantes.

  • Une fois hellosorti, votre code devrait se fermer immédiatement. Il ne faut pas attendre une nouvelle ligne par exemple.

  • Votre code devrait sortir au fur et à mesure. C'est-à-dire qu'il ne devrait pas lire une énorme quantité d'entrée et ensuite commencer la sortie.

  • Si le flux / fichier ne contient pas hello, votre code devrait simplement continuer à sortir l'entrée pour toujours ou jusqu'à la fin du flux / fichier.

  • Il s'agit d'un défi sensible à la casse, il hellon'est donc pas égal à Hello.

  • Vous pouvez supposer que l'entrée se compose uniquement de caractères ASCII imprimables et de nouvelles lignes.

  • Votre code ne peut pas s'attendre à ce que le texte se termine par une nouvelle ligne ou qu'il y ait du tout de nouvelles lignes dans l'entrée. En outre, votre code ne peut pas supposer qu'il fonctionnera sur une machine avec une quantité infinie de mémoire.

  • Vous pouvez supposer que votre code sera appelé à partir d'un répertoire vide.

Exemple de flux d'entrée

I once had a horse called hellopina.

Sortie

I once had a horse called hello

Pointe

Exécutez yes | tr -d \\n | <your program>pour vérifier si cela fonctionne avec des flux infinis. S'il n'imprime rien et / ou fuit la mémoire, le programme n'est pas conforme à la spécification. Il devrait imprimer yyyyyyyyyyyyyyyyyyyyyy...pour toujours sans nouvelle ligne.

Dennis
la source
1
Sommes-nous autorisés à lire quoi que ce soit après le "bonjour"? La question semble interdire toute lecture supplémentaire, ce qui pourrait être problématique dans des langages tels que (Standard) C, qui fournissent une entrée en mémoire tampon avec lecture anticipée automatique.
Toby Speight du
Vous devriez probablement changer la réponse acceptée à celle de l'assemblage, car elle est plus courte de 2 octets.
Rɪᴋᴇʀ
@Riker Ce serait formidable si quelqu'un pouvait le tester ou au moins dire qu'il croyait que cela fonctionnait en premier.

Réponses:

2

Gelée , 24 octets

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

Essayez-le en ligne!

Explication:

ṫ-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.
Erik le Outgolfer
la source
26

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

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

Essayez-le en ligne!

Comment ça marche

Ceci est un programme complet. Nous définissons une fonction f pour nos besoins. Pour enregistrer les octets, il est déclaré avec deux arguments par défaut int . Il s'agit d'un comportement non défini, mais dans la pratique, n sera initialisé à 1 lors de l'exécution du programme sans arguments supplémentaires, c contiendra les 32 bits inférieurs du pointeur sur le vecteur d'argument

Alors que la condition

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

Peut contenir, nous exécuterons le tout le corps de la boucle:

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

Pour bien comprendre la condition, nous devons d'abord examiner le corps. Pour l'instant, tout ce que nous observons, c'est que c=getchar()lit un seul octet de STDIN (si possible) et le stocke dans la variable c .

La séquence d'octets hello se présente comme suit dans différentes représentations.

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

Tous ceux-ci se situent dans la plage [96, 192) , c/96seront donc évalués à 1 pour chacun de ces octets et à 0 pour tous les caractères ASCII restants. De cette façon, putchar(c)/96*c( putchar imprime et retourne son argument) sera évalué à c si c est `, une lettre minuscule, un {|}~ou le caractère DEL; pour tous les autres caractères ASCII, il sera évalué à 0 .

n est mis à jour en le décalant de cinq bits vers la gauche, puis en XOR le résultat avec le résultat du paragraphe précédent. Étant donné qu'un int fait 32 bits de large (c'est ce que nous supposons dans cette réponse), certains des bits décalés peuvent "tomber de la gauche" (le dépassement d'entier signé est un comportement non défini, mais gcc se comporte comme l'instruction x64 qu'il génère ici). En commençant par une valeur inconnue de n , après l'avoir mise à jour pour tous les caractères de bonjour , nous obtenons le résultat suivant.

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

Notez que les 25 bits inférieurs forment l'entier 0xb33def , qui est la constante magique dans la condition. Bien qu'il existe un certain chevauchement entre les bits de deux octets adjacents, le mappage des octets inférieurs à 96 à 0 garantit qu'il n'y a pas de faux positifs.

La condition se compose de deux parties:

  • ~(getchar()) prend le NOT au niveau du bit du résultat de la lecture (ou de la tentative de lecture) d'un octet de STDIN.

    Si getchar réussit, il retournera la valeur de l'octet de lecture sous forme d' int . Étant donné que l'entrée est entièrement composée de caractères ASCII, l'octet de lecture ne peut avoir que ses 7 bits inférieurs définis, de sorte que le bit non aura ses 25 bits les plus élevés définis dans ce cas.

    Si getchar échoue (plus d'entrée), il renverra -1 et le NOT au niveau du bit sera 0 .

  • n-0xb33def<<7soustrait la constante magique d'avant de n , puis décale le résultat de 7 unités vers la gauche.

    Si les 5 derniers octets lus étaient bonjour , les 25 bits de n les plus bas seront égaux à 0xb33def et la soustraction les mettra à zéro. Décaler la différence donnera 0 car les 7 bits les plus élevés "tomberont sur la gauche".

    D'un autre côté, si les 5 derniers octets lus n'étaient pas bonjour , l'un des 25 bits les plus bas de la différence sera défini; après le décalage, l'un des 25 bits les plus élevés sera.

Enfin, si getchar a réussi et que nous n'avons pas encore imprimé bonjour , l'ET au niveau du bit, tous les 25 bits les plus élevés de l'opérande de gauche et au moins l'un des 25 bits les plus élevés de celui de droite seront définis. De cette façon, &produira un entier non nul et la boucle continue.

D'un autre côté, si l'entrée est épuisée ou si nous avons déjà imprimé bonjour , l'un des opérandes ET au niveau du bit sera zéro, tout comme le résultat. Dans ce cas, nous sortons de la boucle et le programme se termine.

Dennis
la source
Vous devriez probablement mentionner que cela dépend de l'entrée encodée en ASCII, avant de plonger dans l'explication.
Toby Speight
2
@TobySpeight Je ne pense pas qu'il soit courant de spécifier cela. Quel type de codage incompatible ASCII attendez-vous d'une réponse C à utiliser?
Dennis
EBCDIC est le codage évident qui n'est pas ASCII. C ne prescrit aucun codage de caractères particulier (seulement que les chiffres décimaux doivent être représentés par des valeurs consécutives, dans l'ordre).
Toby Speight
le programme ci-dessus s'arrête si le flux contient la chaîne non ascii "« úá ÷ o "1: o 111 6f 2: ÷ 246 f6 3: á 160 a0 4: ú 163 5:« 174
RosLuP
@RosLuP La spécification de défi garantit que l'entrée sera constituée de caractères ASCII imprimables et de nouvelles lignes.
Dennis
19

Bash, 74 75 103 99 88 82 76 bytes

-10 octets grâce à @DigitalTrauma!
-11 octets grâce à @manatwork!
-6 octets grâce à @Dennis!

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

Explication:

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

Essayez-le en ligne!

betseg
la source
2
C'est bien! J'espérais qu'il y aurait une réponse bash.
13

Labyrinthe , 43 41 octets

Merci à Sp3000 pour avoir économisé 2 octets.

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

Essayez-le en ligne!

Explication

L'idée de base est de coder les cinq derniers caractères de la base 256 en un seul entier. Lorsqu'un nouveau caractère arrive, nous pouvons «l'ajouter» en multipliant l'entier par 256 et en ajoutant le nouveau point de code. Si nous voulons regarder uniquement les 5 derniers caractères, nous prenons la valeur modulo 256 5 = 2 40 = 1099511627776. Ensuite, nous pouvons simplement vérifier si cette valeur est égale à 448378203247, ce qui est ce que nous obtenons lorsque nous traitons les points de code de hellosous forme de chiffres de base 256.

Quant au code ... <...>est un peu un idiome de labyrinthe. Il vous permet d'écrire une boucle infinie sans aucun flux de contrôle conditionnel sur une seule ligne, économisant beaucoup d'octets sur les espaces et les sauts de ligne. La condition principale pour que cela fonctionne est qu'il y a deux valeurs disponibles au-dessus de la pile lorsque nous atteignons le <(nous utilisons normalement 0s pour cela, mais la valeur réelle est arbitraire).

Bien sûr, le programme a besoin d'une logique conditionnelle pour savoir quand se terminer. Mais la fin conditionnelle du programme est possible en divisant par une valeur qui est nulle lorsque nous voulons que le programme se termine. La <...>construction fonctionne en décalant la ligne entière vers la gauche (cycliquement) lorsque l'IP est à l'extrémité gauche, puis en la remettant immédiatement en position. Cela signifie que le code est en fait exécuté de droite à gauche. Inversons-le:

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

Il s'agit d'une itération de la boucle qui lit un caractère, se termine si nous avons atteint EOF, imprime le caractère, l'ajoute à notre codage, le tronque à 5 caractères, vérifie l'égalité avec helloet répète. Voici comment cela fonctionne en détail (rappelez-vous que Labyrinth est basé sur la pile):

_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.
Martin Ender
la source
8

Brainfuck, 658 octets

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

Plus de 500 octets sont dans les constantes dont j'ai besoin pour jouer un peu au golf.

Il s'agit essentiellement d'une machine à états, donc l'entrée infinie n'est pas un problème.

Ceci est la version légèrement commentée

+
[
  >,.
  >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]
            <->>
          ]
        ]
      ]
    ]
  ]
  <<
]
jvluso
la source
Cela a l'air amusant :)
Bienvenue dans la programmation de puzzles et de code Golf StackExchange!
betseg
1
Ce code a plusieurs problèmes, mais le plus gros problème est qu'il n'inclut pas de logique pour gérer ahehellobcorrectement les cas ; au milieu d'une correspondance potentielle, il ne vérifie que la prochaine lettre helloet ne cherche pas hà recommencer.
Mitch Schwartz
8

Bash , 73 68 66 octets

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

Suppose un répertoire sans ou uniquement des fichiers cachés. Doit être exécuté en tant que <path/to/script>.

Essayez-le en ligne!

Comment ça marche (obsolète)

Au début de la en boucle, nous avons d' abord test si la chaîne dans la variable s (vide au départ) est égal à olleh ( bonjour en arrière, olé), et retour 0 (jeu) ou 1 (pas un match) en conséquence. Bien que faisant officiellement partie de la condition de la boucle, le résultat ne l'affectera pas de lui-même, car seule la dernière commande avant dodétermine si la condition est vérifiée.

Ensuite, nous définissons le séparateur de champ interne sur la chaîne vide (donc readne nous étouffons pas sur les espaces), lisons les octets bruts ( -r) de STDIN et les stockons c. $?est le code de sortie de la commande précédente, il lit donc exactement un ( -N1) octet pour une non-correspondance et zéro octet ( -N0). La lecture de zéro octet, que ce soit en raison de la frappe d'EOF ou parce qu'elle a -N0été spécifiée, provoque la readsortie avec le code d'état 1 , de sorte que la boucle while se terminera; sinon, le corps est exécuté et nous recommençons.

Dans le corps, nous imprimons d'abord l'octet que nous lisons, puis mettons à jour s avec s=$c${s::4}. Cela ajoute l'octet de lecture aux quatre premiers octets de s , jusqu'à ce que s soit égal à olleh une fois que hello a été imprimé.

Dennis
la source
Très beau effectivement!
8

brainfuck, 117 octets

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

Formaté:

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

Essayez-le en ligne .

Cela initialise la bande avec les caractères en hellodécalage par 107, espacés d'une valeur toutes les trois cellules, puis garde une trace des cinq derniers caractères vus et vérifie une correspondance avec chaque nouveau caractère traité, en utilisant un indicateur à droite de la chaîne pour garder une trace s'il y a eu un match.

Mitch Schwartz
la source
7

Rubis , 46 60 octets

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

Essayez-le en ligne!

Lit les caractères de stdin jusqu'aux 5 derniers hello, puis sort la chaîne (ou jusqu'à ce qu'il ne reste aucun caractère dans stdin). Se termine avec une erreur.

Équivalent à:

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

Ou, plus non golfé:

a = ""
loop do
    q = STDIN.getc
    break if a[-5..-1] == "hello" or not q
    a += q
    print q
end
Conor O'Brien
la source
1
agrandit chaque fois qu'un caractère est lu. Est-ce que cela plante si l'entrée est infinie?
betseg
@betseg hm, peut-être. Voyons si je peux résoudre ce problème
Conor O'Brien
7

Python 3, 120 116 104 104 octets

Fonctionne avec des ruisseaux infinis, golf pour la première fois, tous les conseils sont appréciés.

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

Merci @DJMcMayhem d'avoir enregistré quelques octets :)

R. Martin
la source
Bienvenue sur le site! c=[0,c+1]['hello'[c]==a]devrait vous faire économiser quelques octets. Aussi, a=1est plus court aussi.
DJMcMayhem
2
Vous n'avez pas besoin de la parenthèse pour whileen Python.
PurkkaKoodari
6

Haskell, 41 47 43 octets

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

La paresse de Haskell gère bien l'entrée / sortie infinie.

Essayez-le en ligne!

Edit: ne gérait pas d'entrée finie - corrigé. Merci @Leo de l'avoir signalé.

Edit II: @ Ørjan Johansen a enregistré 4 octets. Merci!

nimi
la source
2
L'entrée peut également être finie, donc je pense que vous devez traiter le cas lorsque vous atteignez la fin de la chaîne
Leo
@Leo: Oups, je l'ai totalement raté. Fixé.
nimi
2
Le premier garde peut être raccourci |w@"hello"<-take 5l=w.
Ørjan Johansen
@ ØrjanJohansen: oh, c'est sympa. Merci!
nimi
6

Cubix, 94 83 82 79 63 56 octets

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

Étendu:

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

Remarques

  • L'interpréteur désactive le champ de saisie au démarrage du programme. En tant que tel, un flux d'entrée infini est impossible. Ce programme prend l'entrée caractère par caractère, donc s'il n'y avait pas cette limitation, il fonctionnerait correctement.
  • Ce programme ne vide pas la pile et il devient très rapidement désordonné. Étant donné que la machine sur laquelle cela sera utilisé peut apparemment fournir des flux d'entrée infinis, il semble raisonnable de supposer qu'elle possède également une mémoire infinie.
  • Toute aide au golf est très appréciée.

Essayez-le en ligne

Vous pouvez essayer le programme ici .

Explication

Idée générale

L'idée générale est que nous voulons lire un caractère, puis le comparer à différents caractères (d'abord h, puis e, puisl etc.). Pour garder une trace du personnage que nous avons manqué, nous le gardons tout en bas de la pile. Lorsque nous en avons besoin, nous pouvons facilement le ramener au sommet.

Boucle de lecture / écriture

La boucle de lecture-écriture est simplement la 5 ème ligne. Tous les caractères non utilisés sont remplacés par no-ops ( .):

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

Cela peut être divisé en deux parties: lecture et (écriture et vérification). La première partie contient les instructions jusqu'au point d'interrogation inclus. La deuxième partie est le reste de la ligne. Parce que cela tourne en boucle, nous supposons que nous commençons avec une pile de[...]

    @
'hqi?
    _

Explanation
'h          Push the character code of the h
            Stack: [..., 104]
  q         Send it to the bottom
            Stack: [104, ...]
   i        Read one character of the input (-1 for EOF)
            Stack: [104, ..., input]
    ?       Start of condition:
              if (input < 0):
    @           execute '@', ending the program
              if (input = 0):
                continue going right
              if (input > 0):
    _           turn to the right, reflect back ('_') and
                turn right again, effectively not changing 
                the direction at all

La deuxième partie (écriture et vérification) est de nouveau linéaire. La pile commence comme [next-char, ..., input]. Nous avons résumé le caractère suivant, car cela change plus tard dans le programme.

oqB-!ul.-  Explanation
o          Output the character at the top of the stack
 q         Send the input to the bottom of the stack
           Stack: [input, next-char, ...]
  B        Reverse the stack
           Stack: [..., next-char, input]
   -       Push the difference of the top two characters, which
           is 0 if both are equal, something else otherwise
           Stack: [..., next-char, input, diff]
    !      if (diff = 0):
     u       make a u-turn to the right
           else:
      l.     execute two no-ops
        -    push [input - next-char - input], which is disregarded
             later, so it effectively is a no-op as well.

Maintenant, l'IP recommencera au début de cette boucle, réinitialisant le caractère suivant à vérifier h.

Faire correspondre le caractère suivant

Si l'IP a fait demi-tour (c'est-à-dire que le caractère que nous avons lu et imprimé correspondait au caractère suivant 'hello'), nous devons vérifier quel caractère était l'entrée et en fonction de cela, pousser le caractère suivant au bas de la pile. Après cela, nous devons retourner à la boucle de lecture / écriture, sans pousser hvers la pile, nous avons donc besoin d'un autre moyen pour y arriver.

Tout d'abord: déterminez le caractère de l'entrée. La pile ressemble à ceci: [..., prev-char, input, 0].

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

Pour comparer l'entrée, nous utilisons à nouveau le code de caractère de h. Au départ, c'était parce que je ne savais pas vraiment comment j'allais gérer cela et hc'est le premier caractère de la chaîne à vérifier, mais cela s'est avéré assez pratique. Si nous soustrayons le code de caractère de h de l'entrée, nous obtenons -3si l'entrée est e, 0si l'entrée est h, 4si l'entrée est let 7si l'entrée l'est o.

C'est utile, car la ?commande nous permet de séparer facilement les valeurs négatives des valeurs positives et zéro. En tant que tel, si l'IP tourne à gauche, la différence était négative, donc l'entrée était e, donc le caractère suivant devrait être un l. Si l'IP continue d'aller tout droit, la différence était 0, donc l'entrée était h, donc le caractère suivant devrait être un e. Si l'entrée est un lou un o, l'IP tourne à droite.

Toutes les instructions exécutées avant le point d'interrogation susmentionné sont:

;!e'h-     Explanation
;          Delete the top of the stack
           Stack: [..., prev-char, input]
 !         if (input = 0):
  e          execute 'e' (no-op)
   'h      Push the character code of h
           Stack: [..., prev-char, input, 104]
     -     Push the difference of the input and 104
           Stack: [..., prev-char, input, 104, diff]

Maintenant, l'IP change de direction comme détaillé ci-dessus. Passons en revue les différentes possibilités.

Contribution 'e'

Nous allons d'abord considérer l'entrée e, ce qui fait que l'IP se déplace vers le haut depuis le ?, car la différence est de 3. Tous les caractères non pertinents ont été supprimés du cube.

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

Les caractères sont exécutés dans cet ordre (à l'exception de certains caractères de flux de contrôle):

q'l$WWq
q           Save the difference (-3) to the bottom of the stack so
            we can tell whether the l on the bottom of the stack is
            the first or the second l in hello
            Stack: [-3, ...]
 'l         Push the character code of l to the stack
            Stack: [-3, ..., 108]
   $W       no-op
     W      Sidestep into the loop
      q     Send the character code to the bottom
            Stack: [108, -3, ...]

Maintenant, l'IP a de nouveau atteint la boucle de lecture / écriture.

Contribution 'h'

Si l'entrée était 'h', la différence est 0, donc l'IP ne change pas de direction. Voici à nouveau le cube, avec tous les caractères non pertinents supprimés. Puisque ce chemin comprend pas mal d'opérations, toutes les opérations qu'il passe ont été remplacées &. L'IP commence au point d'interrogation.

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

Les instructions exécutées sont les suivantes:

'e!\?q_
'e          Push the character code of the e
            Stack: [..., 101]
  !         if (101 = 0):
   \          reflect away (effectively a no-op)
    ?       if (101 > 0):
              turn right (always happens)
     q      Move 101 to the bottom of the stack
            Stack: [101, ...]
      _     No-op

Et maintenant, nous entrons à nouveau dans la boucle de lecture / écriture, nous avons donc terminé.

Autres entrées

Toutes les autres entrées entraînent une différence positive, donc l'IP tourne à droite au point d'interrogation. Nous devons encore séparer le let leo , c'est donc ce que nous ferons ensuite.

Séparer le 'l' et'o'

Gardez à l'esprit que la différence est de 7 pour oet 4 pour let que nous devons mettre fin au programme si l'entrée était un o. Voici à nouveau le cube avec les parties non pertinentes remplacées par un .et les no-ops que les croisements IP ont été remplacés par des esperluettes.

        . . q .
        . ? w .
        . h ' .
        . U 7 .
. . . . . . . . . . . . . - . .
. . . . . . . . . . . . . & . .
. . . . . . / ! @ . . . . & . .
. . . . . . & . . . . . . & . .
        . . & .
        . . & .
        . . & .
        . . & .

h7'wq-!@    
h           no-op
 7          Push 7 to the stack
            Stack: [..., diff, 7]
  'wq       Push w to the stack and send it to
            the bottom. We don't care about it,
            so it's now part of the ellipsis.
            Stack: [..., diff, 7]
     -!     if (diff = 7):
       @        End the program

Discerner entre les deux 'l's

Donc, maintenant nous savons que l'entrée était un l, mais nous ne savons pas lequel l. Si c'est le premier, nous devons en pousser un autre lau bas de la pile, mais si c'est le second, nous devons pousser un o. Rappelez-vous que nous avons enregistré -3au bas de la pile juste avant de pousser le premier l? Nous pouvons l'utiliser pour séparer les deux branches.

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

La pile commence comme [..., -3 or 140, ...]

Explanation
6t?         
6t          Take the 6th item from the top and move
            it to the top (which is either -3 or 140)
  ?         If that's positive, turn right, otherwise,
            turn left

Première 'l'

Si ce fut le premier 'l', nous devons en pousser un autre 'l'. Pour économiser des octets, nous utilisons les mêmes caractères que pour le premier 'l'. Nous pouvons simplifier la pile [...]. Voici la partie pertinente du cube, avec aucune opération remplacée par des esperluettes.

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

Les instructions suivantes sont exécutées:

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

Nous sommes sur le point d'entrer dans la boucle de lecture / écriture, nous avons donc terminé avec cette branche.

Seconde 'l'

Si l'entrée était le deuxième 'l'dans 'hello'l'IP a tourné à droite au point d'interrogation. Encore une fois, nous pouvons simplifier la pile [...]et l'IP commence à ?, pointant cette fois vers le sud.

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

Les instructions exécutées sont les suivantes:

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

Et l'IP est sur le point d'entrer à nouveau dans la boucle de lecture / écriture, nous avons donc terminé avec cette branche également.

Luc
la source
Un effort héroïque!
5

C ++, 142 141 octets

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

Essayez-le en ligne!

Steadybox
la source
Serait-ce possible avec GCC? Je ne vois pas #importdans les programmes GCC C ++ ...
ckjbgames
1
@ckjbgames #importest une extension GCC obsolète.
Steadybox
1
@ckjbgames plus d'informations ici: stackoverflow.com/questions/172262/…
iFreilicht
@iFreilicht Cette question m'a fait poser cette question.
ckjbgames
1
@ckjbgames vous voudrez peut-être jeter un œil à la deuxième réponse: stackoverflow.com/a/172264/2533467 "L'importation dans gcc est différente de l'importation dans VC ++. C'est un moyen simple d'inclure un en-tête au maximum une seule fois. "
iFreilicht
3

Noeud, 124 octets

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

Ne pas supposer que le flux tiendra dans la mémoire disponible.

Neil
la source
3

C #, 134 octets

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

Essayez-le en ligne

Lit un caractère, vérifie que ce n'est pas -1 (EOS) et que nous n'avons pas encore vu "bonjour", puis l'ajoute à une chaîne et écrit le caractère. Nous ajoutons car s[0]c'est beaucoup plus court que (char)s. Cela a un coût quadratique dans la longueur de la chaîne, car il doit allouer et analyser l'intégralité de l'entrée à chaque fois qu'il lit un caractère (cela se bloquera après 2 Go d'entrée en raison de contraintes dans le CLR, est-ce autorisé?)

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

Pour une version (plus longue: 142 octets) qui ne manquera pas de mémoire et qui a un coût par caractère constant, voir ci-dessous:

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

Celui-ci conserve les 5 derniers caractères dans une chaîne de 5 longueurs, ce qui signifie de courtes comparaisons et une recherche de dernier caractère bon marché, mais sa mise à jour est considérablement plus coûteuse.

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;
    }
}
VisualMelon
la source
3

PHP, 57 55 53 octets

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

comme il n'y a pas de fichiers infinis, je prends l'entrée de STDIN. Courir avec-nr .

Parcourez l'entrée, imprimez le caractère actuel, ajoutez-le $s, coupez $saux 5 derniers caractères. Briser la boucle quand $sc'est hello.

Titus
la source
3

Vim, 39 octets

:im hello hello:se noma
:map : i

i

Essayez-le en ligne!

: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
nmjcman101
la source
Est-ce une méthode d'entrée acceptée pour Vim? Je pensais que les programmes Vim s'attendent généralement à ce que l'entrée soit déjà dans le tampon avant de commencer.
Martin Ender
Pour être honnête, je ne sais pas? C'est vrai, mais ne permet guère un flux infini, alors je l'ai fait de cette façon sans vraiment y penser.
nmjcman101
Que se passe-t-il s'il y a un caractère d'échappement dans le flux d'entrée?
dim
@dim, ai-je demandé, et OP n'a spécifié que l'ASCII imprimable et les sauts de ligne. ESC n'est pas inclus dans afaik ASCII imprimable
nmjcman101
3

PowerShell, 111 octets

Il y a probablement une meilleure façon de le faire, mais je ne peux pas le voir pour le moment.

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

Cela lit les touches sans supprimer l'écho. Le caractère est ajouté à $ x qui est coupé aux 5 derniers caractères et comparé à "bonjour". Cela continue jusqu'à ce que la comparaison soit vraie.

Remarque: cela ne fonctionne pas dans PowerShell ISE. ReadKey est désactivé dans cet environnement.

MickyT
la source
3

Schéma 115 octets

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

Version lisible:

(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

Cela prend un caractère individuel de stdin à chaque fois dans la boucle et marque sa position sur le mot cible lorsqu'il rencontre les caractères de "bonjour".

Arrête lorsque l'entrée est épuisée ou "bonjour" a été vu. Aucune mémoire utilisée sur le flux infini.

peter
la source
Cool réponse, bienvenue sur le site!
DJMcMayhem
3

AWK, 95 octets

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

Il y a 2 choses que j'ai apprises ici:
1) Pour répartir les enregistrements entre les caractères, utilisez RS="(.)"et RTdevez les utiliser à la place de $1
2) ORSest utilisé par printet est par défaut "\n"
3) Je ne peux pas compter jusqu'à 2 et utiliser printfest "moins cher" que l'attributionORS et en utilisantprint

Exemple d'utilisation: Placer le code dans FILE

awk -f FILE some_data_file

ou

some process | awk -f FILE

Le code a été testé en utilisant la yes | ...suggestion de Dennis et j'ai vu beaucoup, beaucoup dey s.

Pour info, vous pouvez faire l'affectation RS en option et le retirer du BEGINbloc via:

awk -v RS='(.)'
Robert Benson
la source
Solution vraiment délicate! (Peut - être parce que c'est vendredi après - midi, mais je trouve une bonne entrée pour défi Obfuscated aussi.) Bien que je voudrais essayer une approche plus awkish: BEGIN{RS="(.)"}{printf RT}"olleh"==a=RT substr(a,1,4){exit}.
manatwork
Curieusement, j'ai presque exactement répondu prêt à soumettre il y a une heure ... et j'ai oublié de le soumettre. : p
Robert Benson
3

Python 3 (Linux), 73 72 octets

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

Merci à @MitchSchwartz d'avoir joué au golf sur 1 octet!

Essayez-le en ligne!

Dennis
la source
Je ne comprends pas. Comment la condition pour whileévaluer correctement? Il semble que vous compariez un booléen à une chaîne vide.
iFreilicht
1
s[print(end=c):4]enregistre un octet
Mitch Schwartz
1
@iFreilicht Python analyse les conditions chaînées comme on le ferait en mathématiques ( a <b <c , par exemple). La condition est un raccourci pour 'olleh'!=s and s>''and''<c). Le test du milieu n'est pas nécessaire, mais les enchaîner est plus court que le simple 'olleh'!=s and''<c.
Dennis
@MitchSchwartz C'est le cas. Merci!
Dennis
3

8086 code machine, 22 octets

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

Code d'assemblage équivalent:

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"
user5434231
la source
Comment ça marche?
1
J'ai ajouté le code d'assemblage équivalent. Il repose essentiellement sur un syscall DOS très utile, qui lit un octet de stdin et le renvoie en retour à stdout en même temps. Le 8086 a également une instruction de comparaison de chaînes à un octet qui est utile ici.
user5434231
2

Pyth, 49 47 octets

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

Pyth n'est pas très bon pour prendre un seul caractère d'entrée. Tout en$__import__("sys").stdin.read(1) fait simplement cela. Cela signifie également que cela ne fonctionne que hors ligne.

Tout le reste est court ...

Le programme est une boucle while sans corps. À l'intérieur de la condition, le programme lit un caractère, l'imprime à nouveau, ajoute ce caractère à k(qui est initialement la chaîne vide), supprime tous les caractères sauf les 5 derniers k, puis vérifie que le résultat n'est pas"hello" .

32 caractères reçoivent un octet d'entrée, 15 caractères font le reste.

Testé sous Linux, fonctionne même sans nouvelle ligne, entrée infinie, etc.

isaacg
la source
2

Lua, 68 64 octets

l=""while l~="hello"do c=io.read(1)io.write(c)l=l:sub(-4)..c end
Jaser
la source
1
Modifiez le découpage en l:sub(-4), vous pouvez alors réduire l'initialisation de l="".
manatwork
@manatwork C'est bien. Merci pour le conseil.
Blab
2

Rubis, 59 49 48 43 octets

Maintenant sans diatribe, plus court et sans fuite de mémoire.

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

5 octets enregistrés en se débarrassant de quelques parenthèses et d'un espace grâce à Dennis

daniero
la source
Continuons cette discussion dans le chat .
daniero
1

Röda , 49 47 octets

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

Essayez-le en ligne!

Il s'agit d'une fonction anonyme qui lit les caractères de son flux d'entrée et les restitue jusqu'à ce que "bonjour" soit trouvé. Il utilise le tableaua pour suivre les derniers caractères.

Il envoie des ordures à STDERR, mais j'ai compris que cela est autorisé .

Explication:

{
    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. */
}
fergusq
la source
Où est la documentation Roda?
ckjbgames
@ckjbgames Ici. J'utilise la dernière version 0.12, qui est dans sa propre branche dans Github.
fergusq
1

Java 7, 122 118 124 124 123 150 141 octets

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

Arrête maintenant lorsque la fin du flux est atteinte. Gère maintenant des entrées infinies sans manquer de mémoire.

Poussée
la source
Je parie que cela ne peut pas gérer une entrée infinie.
Titus
@Titus fixed ...
Poke
J'ai downvoté sans voir writeêtre utilisé à la place de print. Je ne peux pas annuler mon downvote, désolé pour cela :(
Olivier Grégoire
1

Rubis, 51 octets

x="";$><<x[-1]while/hello./!~x=x[/.{0,5}$/]+$<.getc
  • N'attend pas de nouvelles lignes
  • Fonctionne avec une entrée infinie
GB
la source
1

AHK , 116 octets

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

Il n'y a vraiment rien d'intelligent ou de magique là-dedans. La variable %1%est le premier argument passé et doit être un chemin de fichier avec le flux. Le fichier doit être enregistré lors de sa mise à jour mais le code sera lu jusqu'à la fin même s'il se développe après le début de la lecture.

Ingénieur Toast
la source
1

Mathematica, 107 octets

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

La sortie devient un champ où l'utilisateur peut taper du texte à l'infini (y compris les retours à la ligne) jusqu'à ce que les 5 derniers caractères soient égaux à "hello"; à ce point, il sort.

engourdi
la source
1

brainfuck , 281 octets

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

Je ne sais pas pourquoi, mais je sentais juste que le brainfuck était la bonne chose à faire. Ne nécessite pas de mémoire infinie et peut sortir indéfiniment.

Expliqué

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
]

Essayez-le en ligne!

ATaco
la source
J'allais le faire comme ça, mais je me suis alors rendu compte que cela produisait le zéro octet à l'infini pour une entrée qui ne contient pas "bonjour": tio.run/nexus/…
KarlKastor
Cela échoue également ahehellob.
Mitch Schwartz