Tâche
Lisez un flux de texte ou un fichier éventuellement infini, en affichant son contenu jusqu'à ce que le mot hello
soit sorti, en respectant les règles suivantes.
Une fois
hello
sorti, 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
hello
n'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.
Réponses:
Gelée , 24 octets
Essayez-le en ligne!
Explication:
la source
C (gcc) ,
8180767572717069 octetsEssayez-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
Peut contenir, nous exécuterons le tout le corps de la boucle:
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.
Tous ceux-ci se situent dans la plage [96, 192) ,
c/96
seront 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.
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<<7
soustrait 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.
la source
Bash,
747510399888276 bytes-10 octets grâce à @DigitalTrauma!
-11 octets grâce à @manatwork!
-6 octets grâce à @Dennis!
Explication:
Essayez-le en ligne!
la source
Labyrinthe ,
4341 octetsMerci à Sp3000 pour avoir économisé 2 octets.
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
hello
sous 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 normalement0
s 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: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
hello
et répète. Voici comment cela fonctionne en détail (rappelez-vous que Labyrinth est basé sur la pile):la source
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
la source
ahehellob
correctement les cas ; au milieu d'une correspondance potentielle, il ne vérifie que la prochaine lettrehello
et ne cherche pash
à recommencer.Bash ,
736866 octetsSuppose 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
do
détermine si la condition est vérifiée.Ensuite, nous définissons le séparateur de champ interne sur la chaîne vide (donc
read
ne nous étouffons pas sur les espaces), lisons les octets bruts (-r
) de STDIN et les stockonsc
.$?
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 laread
sortie 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é.la source
brainfuck, 117 octets
Formaté:
Essayez-le en ligne .
Cela initialise la bande avec les caractères en
hello
décalage par107
, 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.la source
Rubis ,
4660 octetsEssayez-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 à:
Ou, plus non golfé:
la source
a
grandit chaque fois qu'un caractère est lu. Est-ce que cela plante si l'entrée est infinie?Python 3,
120116104 104 octetsFonctionne avec des ruisseaux infinis, golf pour la première fois, tous les conseils sont appréciés.
Merci @DJMcMayhem d'avoir enregistré quelques octets :)
la source
c=[0,c+1]['hello'[c]==a]
devrait vous faire économiser quelques octets. Aussi,a=1
est plus court aussi.while
en Python.Haskell,
414743 octetsLa 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!
la source
|w@"hello"<-take 5l=w
.Cubix,
94 83 82 79 6356 octetsÉtendu:
Remarques
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
, puise
, 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 (
.
):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
[...]
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.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 pousserh
vers 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]
.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 eth
c'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-3
si l'entrée este
,0
si l'entrée esth
,4
si l'entrée estl
et7
si l'entrée l'esto
.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 étaite
, donc le caractère suivant devrait être unl
. Si l'IP continue d'aller tout droit, la différence était0
, donc l'entrée étaith
, donc le caractère suivant devrait être une
. Si l'entrée est unl
ou uno
, l'IP tourne à droite.Toutes les instructions exécutées avant le point d'interrogation susmentionné sont:
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.Les caractères sont exécutés dans cet ordre (à l'exception de certains caractères de flux de contrôle):
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.Les instructions exécutées sont les suivantes:
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
l
et 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
o
et 4 pourl
et que nous devons mettre fin au programme si l'entrée était uno
. 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.Discerner entre les deux
'l'
sDonc, maintenant nous savons que l'entrée était un
l
, mais nous ne savons pas lequell
. Si c'est le premier, nous devons en pousser un autrel
au bas de la pile, mais si c'est le second, nous devons pousser uno
. Rappelez-vous que nous avons enregistré-3
au bas de la pile juste avant de pousser le premierl
? Nous pouvons l'utiliser pour séparer les deux branches.La pile commence comme
[..., -3 or 140, ...]
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.Les instructions suivantes sont exécutées:
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.Les instructions exécutées sont les suivantes:
Et l'IP est sur le point d'entrer à nouveau dans la boucle de lecture / écriture, nous avons donc terminé avec cette branche également.
la source
C ++,
142141 octetsEssayez-le en ligne!
la source
#import
dans les programmes GCC C ++ ...#import
est une extension GCC obsolète.Noeud, 124 octets
Ne pas supposer que le flux tiendra dans la mémoire disponible.
la source
C #, 134 octets
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é?)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:
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.
la source
PHP,
57 5553 octetscomme 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$s
aux 5 derniers caractères. Briser la boucle quand$s
c'esthello
.la source
Vim, 39 octets
Essayez-le en ligne!
la source
PowerShell, 111 octets
Il y a probablement une meilleure façon de le faire, mais je ne peux pas le voir pour le moment.
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.
la source
Schéma 115 octets
Version lisible:
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.
la source
AWK, 95 octets
Il y a 2 choses que j'ai apprises ici:
1) Pour répartir les enregistrements entre les caractères, utilisez
RS="(.)"
etRT
devez les utiliser à la place de$1
2)
ORS
est utilisé parprint
et est par défaut"\n"
3) Je ne peux pas compter jusqu'à 2 et utiliser
printf
est "moins cher" que l'attributionORS
et en utilisantprint
Exemple d'utilisation: Placer le code dans FILE
ou
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
BEGIN
bloc via:la source
BEGIN{RS="(.)"}{printf RT}"olleh"==a=RT substr(a,1,4){exit}
.Python 3 (Linux),
7372 octetsMerci à @MitchSchwartz d'avoir joué au golf sur 1 octet!
Essayez-le en ligne!
la source
while
évaluer correctement? Il semble que vous compariez un booléen à une chaîne vide.s[print(end=c):4]
enregistre un octet'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
.8086 code machine, 22 octets
Code d'assemblage équivalent:
la source
Pyth,
4947 octetsPyth 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 derniersk
, 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.
la source
Lua,
6864 octetsla source
l:sub(-4)
, vous pouvez alors réduire l'initialisation del=""
.Rubis,
59494843 octetsMaintenant sans diatribe, plus court et sans fuite de mémoire.
5 octets enregistrés en se débarrassant de quelques parenthèses et d'un espace grâce à Dennis
la source
Röda ,
4947 octetsEssayez-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 tableau
a
pour suivre les derniers caractères.Il envoie des ordures à STDERR, mais j'ai compris que cela est autorisé .
Explication:
la source
Java 7,
122118124 124123150141 octetsArrête maintenant lorsque la fin du flux est atteinte. Gère maintenant des entrées infinies sans manquer de mémoire.
la source
write
être utilisé à la place deprint
. Je ne peux pas annuler mon downvote, désolé pour cela :(Rubis, 51 octets
la source
AHK , 116 octets
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.la source
Mathematica, 107 octets
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.la source
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é
Essayez-le en ligne!
la source
ahehellob
.