Tarefa
Leia um arquivo ou fluxo de texto possivelmente infinito, produzindo seu conteúdo até que a palavra hello
seja impressa, respeitando as seguintes regras.
Após a
hello
saída, seu código deve sair imediatamente. Não deve esperar por uma nova linha, por exemplo.Seu código deve sair como segue. Ou seja, não deve ler uma quantidade enorme de entrada e começar a produzir.
Se o fluxo / arquivo não contiver
hello
, seu código deve continuar produzindo a entrada para sempre ou até o final do fluxo / arquivo.Este é um desafio que diferencia maiúsculas de minúsculas, portanto
hello
não é igual aHello
.Você pode assumir que a entrada consiste apenas em caracteres ASCII imprimíveis e novas linhas.
Seu código não pode esperar que o texto seja finalizado por uma nova linha ou que haja novas linhas na entrada. Além disso, o código não pode assumir que ele será executado em uma máquina com uma quantidade infinita de memória.
Você pode assumir que seu código será chamado de um diretório vazio.
Exemplo de fluxo de entrada
I once had a horse called hellopina.
Saída
I once had a horse called hello
Gorjeta
Execute yes | tr -d \\n | <your program>
para verificar se ele funciona com fluxos infinitos. Se não imprimir nada e / ou vazar memória, o programa não estará em conformidade com as especificações. Ele deve ser impresso yyyyyyyyyyyyyyyyyyyyyy...
para sempre, sem novas linhas.
Respostas:
Gelatina , 24 bytes
Experimente online!
Explicação:
fonte
C (gcc) ,
8180767572717069 bytesExperimente online!
Como funciona
Este é um programa completo. Definimos uma função f para nossos propósitos. Para salvar bytes, é declarado com dois argumentos que assumem o padrão int . Esse é um comportamento indefinido, mas, na prática, n será inicializado como 1 ao executar o programa sem argumentos adicionais, c manterá os 32 bits inferiores do ponteiro no vetor de argumento
Enquanto a condição
detém, vamos executar o enquanto o corpo de loop:
Para entender completamente a condição, devemos primeiro examinar o corpo. Por enquanto, tudo o que observamos é que
c=getchar()
lê um único byte de STDIN (se possível) e o armazena na variável c .A sequência de bytes hello é exibida da seguinte maneira em diferentes representações.
Tudo isso cai no intervalo [96, 192) , então
c/96
será avaliado em 1 para cada um desses bytes e em 0 para todos os caracteres ASCII restantes. Dessa forma,putchar(c)/96*c
( putchar imprime e retorna seu argumento) será avaliado como c se c for`
uma letra minúscula, um dos{|}~
caracteres ou o caractere DEL; para todos os outros caracteres ASCII, ele será avaliado como 0 .n é atualizado deslocando-o cinco bits para a esquerda e, em seguida, XORing o resultado com o resultado do parágrafo anterior. Como um int tem 32 bits de largura (ou seja, assumimos nesta resposta), alguns dos bits deslocados podem "cair da esquerda" (o excesso de número inteiro assinado é um comportamento indefinido, mas o gcc se comporta como a instrução x64 que gera aqui). Começando com um valor desconhecido de n , depois de atualizá-lo para todos os caracteres de hello , obtemos o seguinte resultado.
Observe que os 25 bits inferiores formam o número inteiro 0xb33def , que é a constante mágica na condição. Embora exista alguma sobreposição entre os bits de dois bytes adjacentes, o mapeamento de bytes abaixo de 96 a 0 garante que não haja falsos positivos.
A condição consiste em duas partes:
~(getchar())
toma o NOT bit a bit do resultado da leitura (ou tentativa de leitura) de um byte de STDIN.Se getchar for bem-sucedido, ele retornará o valor do byte lido como um int . Como a entrada consiste inteiramente de caracteres ASCII, o byte lido pode ter apenas seus 7 bits inferiores configurados, portanto, NOT bit a bit terá seus 25 bits mais altos configurados nesse caso.
Se o getchar falhar (não há mais entrada), ele retornará -1 e o bit a bit NOT será 0 .
n-0xb33def<<7
subtrai a constante mágica de antes de n e , em seguida, desloca o resultado 7 unidades para a esquerda.Se os últimos 5 bytes de leitura foram cumprimentados , os 25 bits mais baixos de n serão iguais a 0xb33def e a subtração os zerará . Mudar a diferença resultará em 0, pois os 7 bits mais altos "cairão à esquerda".
Por outro lado, se os últimos 5 bytes de leitura não foram hello , um dos 25 bits mais baixos da diferença será definido; após a mudança, um dos 25 bits mais altos será.
Finalmente, se getchar foi bem-sucedido e ainda não imprimimos hello , o AND bit a bit, todos os 25 bits mais altos do operando esquerdo e pelo menos um dos 25 bits mais altos do direito serão definidos. Dessa forma,
&
produzirá um número inteiro diferente de zero e o loop continuará.Por outro lado, se a entrada estiver esgotada ou se já tivermos impresso hello , um dos operandos AND bit a bit será zero e o resultado também. Nesse caso, rompemos o loop e o programa termina.
fonte
Bash,
747510399888276 bytes-10 bytes graças a @DigitalTrauma!
-11 bytes graças a @manatwork!
-6 bytes graças a @Dennis!
Explicação:
Experimente online!
fonte
Labirinto ,
4341 bytesAgradecimentos ao Sp3000 por salvar 2 bytes.
Experimente online!
Explicação
A idéia básica é codificar os últimos cinco caracteres na base 256 em um único número inteiro. Quando um novo caractere entra, podemos "anexá-lo" multiplicando o número inteiro por 256 e adicionando o novo ponto de código. Se queremos olhar apenas para os últimos 5 caracteres, assumimos o valor módulo 256 5 = 2 40 = 1099511627776. Em seguida, podemos simplesmente verificar se esse valor é igual a 448378203247, que é o que obtemos quando tratamos os pontos de código de
hello
como base 256 dígitos.Quanto ao código ...
<...>
é um pouco do idioma do labirinto. Permite gravar um loop infinito sem nenhum fluxo de controle condicional em uma única linha, economizando muitos bytes em espaços e feeds de linha. A principal condição para que isso funcione é que existem dois valores descartáveis no topo da pilha quando atingimos o valor<
(normalmente usamos0
s para isso, mas o valor real é arbitrário).Obviamente, o programa precisa de alguma lógica condicional para descobrir quando terminar. Porém, é possível finalizar condicionalmente o programa dividindo-o por um valor zero quando queremos que o programa termine. A
<...>
construção funciona deslocando a linha inteira para a esquerda (ciclicamente) quando o IP está na extremidade esquerda e, em seguida, deslocando-a imediatamente de volta à posição. Isso significa que o código é realmente executado da direita para a esquerda. Vamos reverter:Esta é uma iteração do loop que lê um caractere, termina se alcançamos o EOF, imprime o caractere, adiciona-o à nossa codificação, trunca isso para 5 caracteres, verifica a igualdade
hello
e se repete. Aqui está como isso funciona em detalhes (lembre-se de que o Labyrinth é baseado em pilha):fonte
Brainfuck, 658 bytes
Mais de 500 bytes estão nas constantes que eu preciso jogar um pouco.
É essencialmente uma máquina de estado, portanto, entrada infinita não é um problema.
Esta é a versão ligeiramente comentada
fonte
ahehellob
adequadamente; no meio de uma correspondência em potencial, ele verifica apenas a próxima letrahello
e não procura umh
recomeço.Bash ,
736866 bytesAssume um diretório com nenhum ou apenas arquivos ocultos. Deve ser executado como
<path/to/script>
.Experimente online!
Como funciona (desatualizado)
No início do tempo de loop, que primeiro teste se a cadeia na variável s (inicialmente vazia) é igual a olleh ( Olá para trás, OLE), e retornar 0 (fósforo) ou 1 (não um jogo) em conformidade. Embora formalmente faça parte da condição do loop, o resultado não o afetará por si só, pois apenas o último comando anterior
do
determina se a condição é válida.Em seguida, definimos o separador de campo interno como uma string vazia (para
read
não bloquear o espaço em branco), lemos os bytes brutos (-r
) de STDIN e os armazenamosc
.$?
é o código de saída do comando anterior, portanto, ele lê exatamente um (-N1
) byte para um não-correspondente e zero bytes (-N0
). A leitura de zero bytes, seja devido a bater no EOF ou porque-N0
foi especificado, fazread
com que o código de status 1 seja encerrado; portanto, o loop while terminará; caso contrário, o corpo é executado e recomeçamos.No corpo, primeiro imprimimos o byte que lemos e depois atualizamos s com
s=$c${s::4}
. Isso antecede o byte de leitura a (até) os quatro primeiros bytes em s , então s será igual a olleh depois que o hello for impresso.fonte
brainfuck, 117 bytes
Formatado:
Experimente online .
Isso inicializa a fita com os caracteres
hello
deslocados107
, espaçados com um valor a cada três células, acompanha os últimos cinco caracteres vistos e verifica a correspondência com cada novo caractere processado, usando uma bandeira à direita da string para acompanhar se houve uma correspondência.fonte
Ruby ,
4660 bytesExperimente online!
Lê caracteres de stdin até os últimos 5
hello
, e emite a string (ou até que nenhum caractere seja deixado em stdin). Termina com erro.Equivalente a:
Ou, mais não destruído:
fonte
a
cresce toda vez que um caractere é lido. Isso trava se a entrada é infinita?Python 3,
120116104 bytesFunciona com fluxos infinitos, golfe pela primeira vez, todas as dicas são apreciadas.
Obrigado @DJMcMayhem por salvar alguns bytes :)
fonte
c=[0,c+1]['hello'[c]==a]
você deve economizar alguns bytes. Além disso,a=1
é mais curto também.while
no Python.Haskell,
414743 bytesA preguiça de Haskell lida bem com a entrada / saída infinita.
Experimente online!
Editar: não lida com entrada finita - corrigida. Obrigado @Leo por apontar.
Editar II: @ Ørjan Johansen salvou 4 bytes. Obrigado!
fonte
|w@"hello"<-take 5l=w
.Cubix,
94 83 82 79 6356 bytesExpandido:
Notas
Experimente online
Você pode experimentar o programa aqui .
Explicação
Ideia geral
A idéia geral é que queremos ler um caractere e depois compará-lo com caracteres variados (primeiro
h
, depoise
,l
etc.). Para acompanhar o personagem que perdemos, nós o mantemos no final da pilha. Quando precisamos, podemos facilmente trazê-lo ao topo novamente.Loop de leitura / gravação
O loop de leitura e escrita é simplesmente a 5 ª linha. Todos os caracteres que não são usados são substituídos por no-ops (
.
):Isso pode ser dividido em duas partes: Leitura e (escrita e verificação). A primeira parte contém as instruções até e incluindo o ponto de interrogação. A segunda parte acima é o resto da linha. Como isso ocorre, assumimos que começamos com uma pilha de
[...]
A segunda parte (escrita e verificação) é linear novamente. A pilha começa como
[next-char, ..., input]
. Nós abstraímos o próximo caractere, porque isso muda mais tarde no programa.Agora, o IP será iniciado novamente no início desse loop, redefinindo o próximo caractere para o qual verificar
h
.Combinando o próximo caractere
Se o IP fez uma inversão de marcha (ou seja, o caractere que lemos e imprimimos corresponde ao próximo caractere
'hello'
), precisamos verificar qual caractere foi a entrada e, dependendo disso, empurrar o próximo caractere para o final da pilha. Depois disso, precisamos retornar ao loop de leitura / gravação, sem empurrarh
para a pilha, por isso precisamos de outra maneira de chegar lá.Primeiras coisas primeiro: determine qual caractere a entrada foi. A pilha de parecido com este:
[..., prev-char, input, 0]
.Para comparar a entrada, usamos o código de caractere de
h
novamente. Inicialmente, isso era porque eu realmente não sabia como lidar com isso eh
é o primeiro caractere a ser verificado, mas acabou sendo bastante conveniente. Se subtrairmos o código de caractere h da entrada, obtemos-3
se a entrada ée
,0
se a entrada éh
,4
se a entrada él
e7
se a entrada éo
.Isso é útil, porque o
?
comando permite separar facilmente valores negativos de valores positivos e zero. Como tal, se o IP virar à esquerda, a diferença foi negativa, a entrada foie
, então o próximo caractere deve ser uml
. Se o IP continuar em linha reta, a diferença foi0
, assim como a entradah
, o próximo caractere deve ser ume
. Se a entrada é umal
ou umao
, o IP vira à direita.Todas as instruções executadas antes do ponto de interrogação acima são:
Agora, o IP muda de direção, conforme detalhado acima. Vamos examinar as diferentes possibilidades.
Entrada
'e'
Primeiro, consideraremos a entrada
e
, que faz com que o IP se mova para cima do?
, pois a diferença é 3. Todos os caracteres irrelevantes foram removidos do cubo.Os caracteres são executados nesta ordem (excluindo alguns caracteres de fluxo de controle):
Agora, o IP atingiu o loop de leitura / gravação novamente.
Entrada
'h'
Se a entrada foi
'h'
, a diferença é 0, portanto o IP não muda de direção. Aqui está o cubo novamente, com todos os caracteres irrelevantes removidos. Como esse caminho inclui algumas no-ops, todas as no-ops pelas quais passou foram substituídas por&
. O IP começa no ponto de interrogação.As instruções executadas são:
E agora estamos entrando no loop de leitura / gravação novamente, então terminamos.
Outras entradas
Todas as outras entradas resultam em uma diferença positiva; portanto, o IP vira à direita no ponto de interrogação. Ainda precisamos separar o
l
e oo
, e é isso que faremos a seguir.Separando o
'l'
e'o'
Lembre-se de que a diferença é 7
o
e 4l
e que precisamos encerrar o programa se a entrada for umo
. Aqui está o cubo novamente, com as partes irrelevantes substituídas por a.
e as não operações que o IP cruza foram substituídas por e comercial.Discernimento entre os dois
'l'
sEntão, agora sabemos que a entrada foi uma
l
, mas não sabemos quall
. Se for o primeiro, precisamos empurrar outrol
para o fundo da pilha, mas se for o segundo, precisamos empurrar umo
. Lembre-se de que salvamos-3
no final da pilha pouco antes de empurrarmos o primeirol
? Podemos usar isso para separar os dois ramos.A pilha começa como
[..., -3 or 140, ...]
Primeiro
'l'
Se este foi o primeiro
'l'
, precisamos pressionar outro'l'
. Para salvar bytes, usamos os mesmos caracteres do primeiro'l'
. Podemos simplificar a pilha para[...]
. Aqui está a parte relevante do cubo, com as no-ops substituídas por e comercial.As seguintes instruções são executadas:
Estamos prestes a inserir o loop de leitura / gravação, por isso terminamos com esse ramo.
Segundo
'l'
Se a entrada foi a segunda
'l'
em'hello'
, a IP virou à direita no ponto de interrogação. Mais uma vez, podemos simplificar a pilha[...]
e o IP começa em?
, apontando para o sul dessa vez.As instruções executadas são:
E o IP está prestes a entrar no loop de leitura / gravação novamente, por isso também terminamos com esse ramo.
fonte
C ++,
142141 bytesExperimente online!
fonte
#import
em programas GCC C ++ ...#import
é uma extensão do GCC obsoleta.Nó, 124 bytes
Não assumindo que o fluxo caiba na memória disponível.
fonte
C #, 134 bytes
Experimente Online
Lê um caractere, verifica se não é -1 (EOS) e se ainda não vimos "olá", o prefixo é uma string e o escreve. Anexamos porque
s[0]
é muito menor do que(char)s
. Isso tem um custo quadrático no comprimento da string, pois é necessário alocar e varrer toda a entrada toda vez que ele ler um caractere (isso trava após 2 GB de entrada devido a restrições no CLR, isso é permitido?)Para uma versão (mais longa: 142 bytes) que não ficará sem memória e que tenha um custo constante por caractere, veja abaixo:
Este mantém os últimos 5 caracteres em uma string de 5 comprimentos, o que significa comparações curtas e pesquisa barata de último caractere, mas é consideravelmente mais caro para atualizar.
fonte
PHP,
57 5553 bytescomo não há arquivos infinitos, recebo informações do STDIN. Correr com
-nr
.Repita a entrada, imprima o caractere atual, acrescente-o a
$s
, corte$s
os últimos 5 caracteres. Quebrar o loop quando$s
estiverhello
.fonte
Vim, 39 bytes
Experimente online!
fonte
PowerShell, 111 bytes
Provavelmente existe uma maneira melhor de fazer isso, mas não posso vê-lo no momento.
Isso lê os pressionamentos de tecla sem suprimir o eco. O caractere é adicionado a $ x, que é aparado com os últimos 5 caracteres e comparado com "olá". Isso continua até que a comparação seja verdadeira.
Nota: isso não funciona no PowerShell ISE. O ReadKey está desativado nesse ambiente.
fonte
Esquema 115 bytes
Versão legível:
Isso pega um caractere individual de stdin toda vez que o loop é marcado e marca sua posição na palavra de destino, pois ele encontra os caracteres de "hello".
Pára quando a entrada acaba ou "olá" foi visto. Nenhuma memória usada no fluxo infinito.
fonte
AWK, 95 bytes
Há duas coisas que aprendi aqui:
1) Para dividir registros entre caracteres, use
RS="(.)"
e depoisRT
deve ser usado em vez de$1
2)
ORS
é usado porprint
e tem como padrão"\n"
3) Não posso contar até 2 e usar
printf
é "mais barato" do que atribuirORS
e usandoprint
Exemplo de uso: coloque o código em FILE
ou
O código foi testado usando a
yes | ...
sugestão de Dennis e vi muitos e muitosy
s.Para sua informação, você pode fazer a atribuição de RS como uma opção e retirá-la do
BEGIN
bloco via:fonte
BEGIN{RS="(.)"}{printf RT}"olleh"==a=RT substr(a,1,4){exit}
.Python 3 (Linux),
7372 bytesGraças a @MitchSchwartz por jogar fora um byte!
Experimente online!
fonte
while
avaliar adequadamente? Parece que você está comparando um booleano a uma string vazia.s[print(end=c):4]
salva um byte'olleh'!=s and s>''and''<c)
. O teste do meio não é necessário, mas encadeá-los é mais curto que o simples'olleh'!=s and''<c
.Código de máquina 8086, 22 bytes
Código de montagem equivalente:
fonte
Pitão,
4947 bytesPyth não é muito bom em aceitar um único caractere de entrada. Tudo em
$__import__("sys").stdin.read(1)
é simplesmente fazer isso. Além disso, isso significa que isso é executado apenas offline.Tudo o resto é curto ...
O programa é um loop while sem corpo. Dentro da condição, o programa lê um caractere, o imprime novamente e acrescenta esse caractere ao
k
(que é inicialmente a string vazia), apara todos os caracteresk
, exceto os últimos 5, exceto os últimos 5 caracteres e verifica se o resultado não está"hello"
.32 caracteres estão recebendo um byte de entrada, 15 caracteres fazem o resto.
Testado no Linux, funciona mesmo sem nova linha, entrada infinita, etc.
fonte
Lua,
6864 bytesfonte
l:sub(-4)
, então você pode reduzir a inicialização del=""
.Ruby,
59494843 bytesAgora livre de discursos, mais curto e sem vazamento de memória.
Economizou 5 bytes ao se livrar de alguns parênteses e espaço graças a Dennis
fonte
Röda ,
4947 bytesExperimente online!
Essa é uma função anônima que lê caracteres do fluxo de entrada e os envia até que "hello" seja encontrado. Ele usa a matriz
a
para rastrear os últimos caracteres.Ele gera algum lixo para STDERR, mas entendi que é permitido .
Explicação:
fonte
Java 7,
122118124123150141 bytesAgora para quando o final do fluxo é atingido. Agora lida com entrada infinita sem ficar sem memória.
fonte
write
sendo usado em vez deprint
. Não posso desfazer meu voto negativo, desculpe por isso :(Ruby, 51 bytes
fonte
AHK , 116 bytes
Não há nada inteligente ou mágico lá, realmente. A variável
%1%
é o primeiro argumento passado e deve ser um caminho de arquivo com o fluxo. O arquivo deve ser salvo à medida que for atualizado, mas o código será lido até o fim, mesmo se ele se expandir após o início da leitura.fonte
Mathematica, 107 bytes
A saída se torna um campo em que o usuário pode digitar infinitamente texto (incluindo novas linhas) até que os últimos 5 caracteres sejam iguais
"hello"
; nesse ponto, ele sai.fonte
brainfuck , 281 bytes
Eu não sei por que, mas eu senti que foder o cérebro era a coisa certa a fazer isso. Não requer memória infinita e pode produzir para sempre.
Explicado
Experimente online!
fonte
ahehellob
.