Eco sensível ao tempo


38

fundo

O echoprograma é tão legal. Você pode dizer qualquer coisa, e ele repete suas palavras perfeitamente, sempre! Quão legal é isso! Desapontador, ele repete a entrada de uma só vez, independentemente da sua velocidade de digitação, o que não é muito realista. Nós vamos ter que consertar isso.

A tarefa

Seu programa deve receber sua contribuição do STDIN ou equivalente mais próximo. Ele deve ler as linhas do usuário, uma a uma, possivelmente exibindo algum prompt, até que elas entrem em uma linha vazia. Depois disso, imprimirá as linhas em STDOUT ou equivalente mais próximo, na mesma ordem em que foram dadas. A última linha (vazia) não é impressa e a última linha impressa não precisa ter uma nova linha à direita.

Além disso, o programa deve preservar os intervalos de tempo entre cada linha: se o usuário xlevar alguns segundos para inserir uma linha, levará xalguns segundos para o programa imprimi-la. Isso se aplica também à primeira e à última linha; a linha vazia não é impressa, mas o programa espera mesmo assim antes de terminar.

Exemplo

Aqui está uma sessão de exemplo com o programa. Todas as ações que não produzem texto são descritas entre colchetes, e o prompt (opcional) é exibido como >.

[begin program]
> fhtagn[enter; 1.48s passed since starting program]
> yum yum[enter; 3.33s passed since previous enter]
> so cool![enter; 2.24s passed since previous enter]
> [enter; 0.23s passed since previous enter]
[wait 1.48s]fhtagn
[wait 3.33s]yum yum
[wait 2.24s]so cool!
[wait 0.23s, then end program]

Sem as ações, a sessão fica assim:

> fhtagn
> yum yum
> so cool!
> 
fhtagn
yum yum
so cool!

Regras e Pontuação

Os tempos de espera devem ser precisos em 0,01 segundos (na prática, se o ser humano médio não pode dizer a diferença, você está bem). A menor contagem de bytes vence e as brechas padrão não são permitidas. Se o seu idioma tiver uma função interna precisamente para esta tarefa, você não poderá usá-lo.


9
Próximo passo: Golf um programa que executa um jogo de ritmo básico: P
Sp3000

Podemos desconsiderar o tempo que o programa leva para gerar caracteres? Quero dizer, se eu puder medir que meu idioma leva 0,1 segundos para gerar um char, devo levar isso em consideração? Divulgação completa, planejo usar o tempo de verificação dos intérpretes para implementar o atraso; Nesse caso, posso ter um loop decorrido o tempo de entrada e desconsiderar o tempo decorrido pelo meu loop de exibição?
Aaron

1
@AaronGOUZIT Permitirei isso, desde que você seja consistente: os intervalos de tempo entre os momentos em que seu programa começa a imprimir uma linha são retirados do usuário ou os tempos de espera entre o término da impressão de uma linha e o início da impressão os próximos são retirados do usuário.
Zgarb

1
@TessellatingHeckler Este último; veja a sessão de exemplo.
Zgarb 9/10

1
@KritixiLithos Eu só usei minha mão direita yum yum, o que foi bastante complicado.
Zgarb 9/10/2015

Respostas:


15

CJam, 45 41 39 36 34 bytes

{eslN1$}g;es](es-fm3/{){_es>}g;o}/

Isso realmente não faz sentido no intérprete on-line, é claro, mas funciona no interpretador Java.

Não exibe um prompt.

Explicação

{        e# Do while... (popping the condition from the stack)
  es     e#   Get the current timestamp.
  l      e#   Wait for a line to be entered and read it.
  N      e#   Push a linefeed.
  1$     e#   Copy the line we read - this terminates if the line is empty, because
         e#   empty strings/arrays are falsy.
}g
;        e# Discard the last linefeed (the one after the empty input).
es       e# Push the current timestamp (corresponding to the last, empty, input).
]        e# Wrap everything in an array. This is now a flat array containing:
         e#   - The initial timestamp.
         e#   - Three elements for each line: the line, a linefeed, the timestamp.
         e#   - Two elements for the last line: the empty string and the timestamp.
(        e# Pull off the initial time.
es-      e# Subtract the current time, which gives (minus) the difference between
         e# when a line was entered and when it should be printed back.
fm       e# This maps "minus that value" onto each element in the array. Now the lines
         e# and linefeeds are strings (arrays) - so minus is set difference, but they
         e# only contain characters, not any integers (like the difference value), so
         e# none of the strings will be affected.
         e# The timestamps on the other hand will be incremented by the time difference
         e# between reading and printing, giving the time at which each line should be
         e# printed back.
3/       e# Split the array into chunks of 3 (where the remaining two elements are
         e# just grouped as a pair).
{        e# For each of those chunks...
  )      e#   Pull off the timestamp.
  {      e#   Do while... (popping the condition from the stack)
    _    e#     Duplicate the target time.
    es>  e#     Check if it's still greater than the current time.
  }g
  ;o     e# Discard the target time and print the rest of the current chunk, which will
         e# automatically be flattened/concatenated into a single string.
}/

9

JavaScript, 119 112 bytes

k=(d=Date.now)(i=j=[]);do{i[++j]=[prompt(),d()-k]}while(i[j][0]);i.map(a=>setTimeout(b=>console.log(a[0]),a[1]))

Na esperança de encontrar mais alguns bytes para cortar.


1
Você pode salvar alguns bytes com j=i=[]( ++ainda funcionará!) Também, o seu whilenão precisa !='', pois é falso! Tão decepcionado que eu perdi map! +1
Dom Hastings

1
Boa nota sobre o !=''. Estava preocupado se a entrada era 0, mas parece lidar com isso bem. Eu já havia notado a []possibilidade de incremento antes, mas tinha sido bobo e tentei fazer j++isso. Fazendo ++jobras, já que []++é aparentemente 0 XD Obrigado!
Mwr247

1
Marcar este dia em que soube que havia do...whileloops em JS
Conor O'Brien

6

JavaScript, 120 bytes

Sem chance de chegar perto do CJam com essa abordagem, mas com um script direto.

a=[];t=+new Date;while(s=prompt()){a.push({s:s,t:+new Date})}while(v=a.pop()){setTimeout(`console.log('${v.s}')`,v.t-t)}

1
Parece que nós dois fomos ao JS ao mesmo tempo haha, embora você tenha o seu um pouco antes do meu. Ainda assim, abordagens diferentes.
Mwr247

@ Mwr247 De fato, o seu é mais elegante!
Dom Hastings

6

Pitão, 68 bytes

M&p+Gb$__import__('time').sleep(H)$J].dZWeaYwaJ.dZ)aJ.dZp&gVPY-VtJJk

Desperdiçou muitos bytes na chamada para sleep, já que Pyth não tem sleepfunção.


3
Talvez você deva sugerir isso como um complemento ao Pyth.
mbomb007

Acredito que você tenha um erro pontual na espera. Tente iniciar o programa, aguardando, digitando algo e pressione enter duas vezes rapidamente. Ele imprimirá imediatamente a primeira linha e espere um pouco antes de terminar.
FryAmTheEggman # 9/15

6

Ruby, 74

t,*a=Time.now
a<<[$_,t-t=Time.now]while$/<gets
a.map{|l,i|sleep -i;puts l}

Truques: *ana primeira linha, inicializa uma matriz vazia. Eu poderia usar em $*vez disso, mas é um pouco superficial, pois é preenchido com algumas invocações e só me salva um byte. $/é uma nova linha e $_é a última linha recuperada por gets.

Edit: Dormir no final custa mais 20 bytes, provavelmente uma maneira de jogar golfe

t,*a=Time.now
a<<[$_,t-t=Time.now]while$/<gets
t-=Time.now
a.map{|l,i|sleep -i;puts l}
sleep -t

Eu acho que você precisa dormir na última linha, dependendo de quanto tempo o usuário levou para fornecer uma linha vazia.
Konrad Borowski

Para dormir no final (solução 2), você chama Time.nowo tempo suficiente usando def n;Time.now;end, economizando 2 bytes inteiros
Value Ink

6

Python 3, 124

Funciona apenas em plataformas Windows

from time import*
s=[(1,clock())]
while s[-1][0]:s+=[(input(),clock()-s[-1][1])]
[sleep(y)or x and print(x)for x,y in s[1:]]

Manter a entrada e os horários em listas separadas me custam mais 3 bytes . Provavelmente não é a melhor abordagem.

Uma versão amigável de 129 bytes para Unix, com crédito para o Mego :

from time import*
t=time
s=[(1,t())]
while s[-1][0]:s+=[(input(),t(),t()-s[-1][1])]
[sleep(y)or x and print(x)for x,z,y in s[1:]]

Você não pode usar em time()vez de clock()salvar 2 bytes?
Kirbyfan64sos

4

SWI-Prolog, 185 bytes

a:-b([],S),reverse(S,T),c(T),!.
b(R,S):-get_time(X),read_string(user_input,"\n","",_,A),get_time(Y),Z is Y-X,(A="",S=[A:Z|R];b([A:Z|R],S)).
c([A:Z|T]):-sleep(Z),T=[];(write(A),nl,c(T)).

Provavelmente há muito para jogar golfe aqui, mas isso servirá por enquanto ...


4

PowerShell, 261 190 121 95 Bytes

$(do{Measure-Command{$l=read-host};$l}while($l))|%{($_,(sleep -m($_.Ticks/1e4)))[($b=!$b+!$_)]}

Acessórios para TessellatngHeckler e tomkandy pela assistência e inspiração no golfe

Isso é muito semelhante em conceito à versão de 121 bytes abaixo, estamos apenas criando e construindo dinamicamente uma lista de objetos, em vez de passar por um loop while para armazená-los em uma matriz explícita $a. Nos dois casos, essa lista de objetos é canalizada para o mesmo loop foreach |%{...}. ($b=!$b+!$_)Desta vez, a indexação no seletor de matriz de resultados é formulada para eliminar as if($_){$_}iterações abaixo, o que economiza mais alguns bytes.


Anterior, 121 bytes

$l,$a=1,@();while($l){$t=Measure-Command{$l=read-host};$a+=$t,$l}$a|%{($(if($_){$_}),(sleep -m($_.Ticks/1e4)))[($b=!$b)]}

Expandido e explicado:

$l,$a=1,@()                        # Set variable $l and create array $a
while($l){                         # So long as we don't have a blank line
  $t=Measure-Command{$l=read-host} # Read the input and measure time to input
  $a+=$t,$l                        # Add those values into the array
}
$a|%{                              # For each item in $a, do
  ($(if($_){$_}),(sleep -m($_.Ticks/1e4)))[($b=!$b)]
  # Magic happens here ... first, we set $b to the NOT of it's uninitialized
  # value, so $b is initially set to truthy
  # This value in [...] selects which of the two elements ( , ) get selected
  # Truthy to start means the second command, sleep, gets chosen first, and
  # then it alternates every next item, so it sleeps, then prints, then
  # sleeps, then prints, etc., until we run out of $a
}

Anteriormente, 190 bytes

function f {param($m)sleep -m $a[$m].totalmilliseconds}$a=1,1;while($a[-1]-ne""){$a+=Measure-Command{$b=read-host};$a+=$b}if(!($a[3])){f 2;exit}$i=2;while($i-lt$a.length){f($i++);$a[($i++)]}

function f {                        # Define a new function
  param($m)                         # with $m as input
  sleep -m $a[$m].totalmilliseconds # sleep for $a[$m] milliseconds
}
$a=1,1                              # Create new array with two elements
while($a[-1]-ne""){                 # While the last element isn't empty
  $a+=Measure-Command{$b=read-host} # Read into $b and measure how long that took,
                                    # and add the time into $a
  $a+=$b                            # Then add the input into $a
}
if(!($a[3])){                       # If the third element is empty, the user entered
                                    # a blank as the only input, so...
  f 2                               # sleep for $a[2] ms (how long it took them to hit enter)...
  exit                              # and exit the script
}                                   # Else ...
$i=2                                # Set a counter variable
while($i-lt$a.length){              # While we haven't reached the end of $a
  f($i++)                           # Sleep
  $a[($i++)]                        # Write the output
}

Anterior-er-er, 261 bytes

$a=$d=@();$d+=,@(date);$x=Read-Host
while($x){$a+=,@($x);$d+=,@(date);$x=Read-Host}
if($x){0..($a.Length-1)|%{sleep -m((($d[$_+1]).ticks-($d[$_]).ticks)/1e4);$a[$_]};sleep -m((($d[-1]).ticks-($d[-2]).ticks)/1e4)}
else{sleep -m(((date).Ticks-($d[0]).Ticks)/1e4)}

Sagrada verbosidade, Batman! Vamos dividir:

$a=$d=@()                  # Create two empty arrays
$d+=,@(date)               # Add the current time into $d
$x=Read-Host               # Read the first line
while($x){                 # So long as it's not empty
  $a+=,@($x)               # Add it into our output array
  $d+=,@(date)             # Add the current time into $d
  $x=Read-Host             # Get the next line
}
if($a){                    # So long as $a exists (i.e., the first input wasn't blank)
  0..($a.Length-1)|%{      # For-loop over the length
                           # Sleep for how long it took to do input
    sleep -m((($d[$_+1]).ticks-($d[$_]).ticks)/1e4)
    $a[$_]                 # Print out the input
  }
                           # Sleep the length it took for the final blank
  sleep -m((($d[-1]).ticks-($d[-2]).ticks)/1e4)
}
else{
                           # If we're here, the initial input was blank, so just sleep
  sleep -m(((date).Ticks-($d[0]).Ticks)/1e4)
}

144$a=1,1;while($a[-1]-ne""){$a+=Measure-Command{$b=read-host};$a+=$b};$i=2;while($i-lt$a.length){sleep -m $a[($i++)].totalmilliseconds;$a[($i++)]}
tomkandy

@tomkandy Thanks! Atualizado com melhorias.
AdmBorkBork

@TessellatingHeckler Excellent! Eu estava lutando com uma maneira de controlar a alternância efetivamente, e indexar em uma matriz como essa é a escolha óbvia agora que eu a vejo. Aliás, eu joguei outro byte removendo o @dessa matriz, pois não é necessário nesse contexto, então, para 121 .
AdmBorkBork 10/10

@ TimmyD, o que eu estava tentando ontem foi colocar pares ($ t, $ l) em $ a criando uma matriz aninhada. Não consegui fazê-lo funcionar, mas hoje consegui e ajuda um pouco, porque não há necessidade de alternar, basta ler todos os pares e usá-los. Então eu percebi - temos um pipeline perfeitamente bom que pode enfileirar as coisas, por que manter uma matriz? $($l=1;while($l){Measure-Command{$l=read-host};$l})|%{($_,(sleep -m($_.Ticks/1e4)))[($b=!$b+!$_)]}- e com uma mudança para a alternância, de modo que quando a corda é esvaziá-la não de alternância, e dorme em vez - 98
TessellatingHeckler

(Faça um do{...}while($l)loop e solte $l=1;para obter 95 ) #
TessellatingHeckler 10/10

3

Perl 6, 70 caracteres

repeat {$/=now;.push($!=get,now -$/)}while $!;.map:{sleep $^b;say $^a}

O interpretador Perl 6 define apenas três variáveis ​​simbólicas (diferente da loucura do Perl 5). Para ser exato, $/, $!, e $_. Este programa usa todos eles, para evitar o custo de declarar variáveis ​​usando my.

getlê uma linha de STDIN. Não contém uma nova linha, diferente do Perl 5.

nowbuiltin retorna um horário atual. Quando subtraído, fornece um intervalo que pode ser passado para uma string.

Um método com nada à esquerda (como .pushe .mapneste código) funciona $_.

Usando repeat whileloop (conhecido como do whileem outras linguagens de programação), o Perl 6 está gravando o carimbo de data / hora atual $/e pressiona a linha recebida (na qual ele também armazena $!) e a diferença entre o horário atual e o carimbo de data / hora $/. Devido à ordem dos parâmetros, nownão é calculado até que uma linha seja recebida.

A whilecondição verifica se a linha não está vazia (no Perl 6, "0"é um valor verdadeiro, diferente do Perl 5).

Depois de obter todos os registros de data e hora, apenas forneço aqueles para mapretorno de chamada, que dorme um pouco e diz o que foi dito.


2

Groovy, 202 bytes

def b={System.currentTimeMillis()};def h=[];for(;;){def t=b();def s=System.console().readLine();h.add(s+" "+(b()-t));if(s=="")break};for(def s:h){Thread.sleep((s=s.split(" "))[1].toLong());println s[0]}

Radical.

Versão não destruída:

def b = {System.currentTimeMillis()}; // Creates a closure (short function) b that returns the current time since the epoch in milliseconds.
def h = []; // Makes an empty list
for(;;) { // Infinite loop
  def t = b(); // Get the time
  def s = System.console().readLine(); // Read a line
  h.add(s + " " + b()-t); // Add the string plus the amount of time elapsed to the list
  if(s=="") // If the string is blank
    break; // Exit loop
}
for(def s : h) { // Iterate through array
  Thread.sleep((s=s.split(" "))[1].toLong()); // Splits s into an array and puts the value in s, then takes the second element (the time), converts into a long and sleeps for that time.
  println s[0] // Print the first element (text)
}

2

JavaScript (ES6) 102

Reunindo os esforços de Mwr247 e Dom Hastings (CW)

/* for TEST */ console.log=x=>O.innerHTML+=x+'\n'

for(k=new Date,i=[];p=prompt();i.push([p,new Date]));i.map(a=>setTimeout(b=>console.log(a[0]),a[1]-k))
<pre id=O></pre>


2

MATLAB, 107 99

tic;a={};i=1;while nnz(i);i=input('','s');a=[a;{i,toc}];tic;end;for b=a';pause(b{2});disp(b{1});end

E não destruído:

tic; %Start timer
a={};
i=1; %Make us enter the while loop
while nnz(i); %While i has some non-zero elements (this is used to detect a zero length input where we end)
    i=input('','s'); %Get an input string
    a=[a;{i,toc}]; %Append the string and current time as a new cell in a
    tic; %Restart timer
end
for b=a' %For each input
    pause(b{2}); %Wait for the required time
    disp(b{1}); %Then print the string
end

Isso não será 100% preciso no tempo, pois não leva em consideração o tempo gasto para exibir cada sequência, mas isso deve ser bastante rápido, portanto, em termos de tempo, deve estar bem próximo.


Após uma rápida revisão, salvei alguns bytes removendo a matriz de células profundas de camada dupla. Acontece que tudo que eu precisava era de uma ;separação correta ao embalar.


1
Talvez você possa criar uma versão que jogue golfe no MATL.
Ckjbgames

1

Java, usando a versão 1.04 desta biblioteca , 385 bytes

import sj224.lib.util.*;import java.util.*;class E{static long t(){return System.currentTimeMillis();}public static void main(String[]a) throws Exception{List<Pair<?,Long>>l=new ArrayList();Scanner i=new Scanner(System.in);while(true){long t=t();String s=i.nextLine();if(s.isEmpty())break;l.add(new Pair(s,t()-t));}for(Pair<?,Long>p:l){Thread.sleep(p.two);System.out.println(p.one);}}}

1

ObjectScript em cache, 123 bytes

w() q $P($ZTS,",",2)
r f  s i=i+1,t=$$w() r x,! q:x=""  s g(i,x)=$$w()-t
    f i=1:1 s s=$O(g(i,"")) q:s=""  w s,! h g(i,s)
    q

Como sempre, isso pressupõe uma tabela de símbolos limpa antes da execução d r.

Esse problema não pode ser resolvido no ANSI MUMPS, pois o padrão ANSI requer apenas resolução de segundo nível para o tempo intrínseco $H[OROLOG]. Felizmente, a Intersystems Caché, atualmente a plataforma líder do setor para MUMPS, fornece a $ZT[IME]S[TAMP]intrínseca definida pela implementação , que fornece resolução em microssegundos.

(A pontuação era anteriormente de 105 bytes, mas havia um erro.)


1

C ++ 11, 343 338 bytes

Queria ver quantos bytes um código para isso em c ++ precisaria. Muito mais do que eu esperava. Talvez eu tenha complicado demais a solução.

#include<iostream>
#include<vector>
#include<chrono>
int i;using namespace std;int main(){auto n=chrono::system_clock::now;auto t=n();string s{1};vector<string>r;vector<decltype(t-t)>w;while(s.size())getline(cin,s),r.push_back(s),w.push_back(n()-t),t=n();while(i<r.size()){while((n()-t)<w[i]);t=n();cout<<r[i++]<<(i<r.size()-1?"\n":0);}}  

Vamos ver se eu posso reduzir isso de alguma forma.


Você pode remover os espaços nos se a #includedeclaração de tipo para main. São 7 bytes - não muito, mas um começo. Você também pode ser capaz de usar auto, em vez de stringpara s.
Alex A.

Obrigado pelo feedback. Vou manter o tipo de retorno para o principal. Se bem me lembro, apenas para cisso não precisamos especificar. Eu tentei inicialmente usar auto s... mas parece que ele é convertido const char *e não std::string. Gostaria de saber se posso criar um alias para while.
Wendelbsilva

A remoção do tipo de retorno funciona para C ++, embora "não deva" conforme o padrão. Você pode tentar criar um alias para whileusar um #definetalvez.
Alex A.

1

Bash, 91 90 bytes

while r=`\time -fsleep\ %e head -1`
[[ $r ]]
do printf{,\ %%b\ %q\;} "$r
"
done>t 2>&1
. t

Isso cria um arquivo temporário t. Ele substituirá um arquivo existente com o mesmo nome.

A ideia em si é bem curta, mas lidar com caracteres especiais na entrada adiciona cerca de 15 bytes ...


1

VBA, 233 bytes

Tenho certeza que isso pode ser muito praticado. eles não especificaram quantas entradas, então eu codifiquei meus comprimentos de array porque é mais curtoRedim preserve .

A entrada é via pop-up, a saída é debug.printporquemsgbox produz um código MODAL e pára.

Não sei como testar se isso é preciso para os 0,01s. Talvez alguém possa testar, mas eu estou dando ao comando wait o número de uma maneira que DEVE usar os milissegundos, mas o VBA não é conhecido por fazer o que deveria.

O If gotopode ser capaz de ser substituído por um poço de golfe Do Loop While.

Sub a()
Dim k(99) As String
Dim h(99) As Date
b:
t=Now()
i=i+1
k(i)=InputBox("")
h(i)=Now()-t
If k(i)<>"" Then GoTo b
For u=1 To i
Application.Wait (Now()+(Format(h(u),"s")&Format(h(u),"ms"))/10^8)
Debug.Print k(u)
Next
End Sub

Não funcionará no Access VBA, porque o acesso não tem um comando de espera porque a Microsoft odeia consistência


0

SmileBASIC, 122 bytes

DIM A$[0],T[0]@L
C=MAINCNT
LINPUT S$PUSH A$,S$PUSH T,MAINCNT-C
IF""<S$GOTO@L@P
WAIT SHIFT(T)IF""<A$[0]THEN?SHIFT(A$)GOTO@P

Eu acho que isso poderia ser feito um pouco mais curto.


0

C UNIX, 272 bytes

#include <stdio.h>
#include <unistd.h>
#define P printf
i;r;c;main(){char*L[99]={0};size_t s;long T[99]={0};while(1){P(">  ");T[c]=time(0);r=getline(&L[c],&s,stdin);T[c]=time(0)-T[c];if(r==-1|!(*L[c]-10))break;c++;}while(i<c){P("> ");usleep(T[i]*1000);P("%s", L[i]);i++;}}

Detalhado

#include <stdio.h>
#include <unistd.h>

int main(void)
{
    int i = 0, c = 0, r;
    char * L[99] = {0};
    size_t size;
    long T[99] = {0L};

    while(1)
    {
        printf("> ");
        T[c] = time(0);
        r = getline(&L[c], &size, stdin);
        T[c] = time(0) - T[c];
        if(r == (-1)) break;
        if(*L[c]=='\0' || *L[c]=='\n') break;
        c = c + 1;
    }

    while(i < c)
    {
        printf(" %ld > ",T[i]);
        usleep(T[i]*1000);
        printf("%s", L[i]);
        i = i + 1;
    }

    return 0;
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.