Eco sensible al tiempo

38

Fondo

El echoprograma es muy ordenado. ¡Puedes decirle cualquier cosa, y repite tus palabras perfectamente, siempre! ¡Cuan genial es eso! Decepcionantemente, repite la entrada de una sola vez, independientemente de su velocidad de escritura, que no es muy realista. Tendremos que arreglar eso.

La tarea

Su programa tomará su entrada de STDIN o su equivalente más cercano. Leerá las líneas del usuario una por una, posiblemente mostrando algún aviso, hasta que ingresen una línea vacía. Después de eso, imprimirá las líneas a STDOUT o su equivalente más cercano, en el mismo orden en que se dieron. La última línea (vacía) no se imprime y la última línea impresa no necesita tener una nueva línea final.

Además, el programa preservará los intervalos de tiempo entre cada línea: si el usuario tardó xsegundos en ingresar una línea, xel programa tardará unos segundos en imprimirla. Esto se aplica también a la primera y última línea; la línea vacía no se imprime, pero el programa espera de todos modos antes de finalizar.

Ejemplo

Aquí hay una sesión de ejemplo con el programa. Todas las acciones que no producen texto se describen entre paréntesis y la solicitud (opcional) se muestra 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]

Sin las acciones, la sesión se ve así:

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

Reglas y puntuación

Los tiempos de espera deben ser precisos dentro de 0.01 segundos (en la práctica, si el humano promedio no puede notar la diferencia, está bien). El conteo de bytes más bajo gana, y las lagunas estándar no se permiten. Si su idioma tiene una función incorporada para precisamente esta tarea, no puede usarla.

Zgarb
fuente
9
Siguiente paso: Golf un programa que juega un juego de ritmo básico: P
Sp3000
¿Podemos ignorar el tiempo que tarda el programa en generar caracteres? Quiero decir, si puedo medir que mi idioma tarda 0.1 segundos en generar un char, ¿debería tenerlo en cuenta? Divulgación completa, estoy planeando usar el tiempo de tick de los intérpretes> <> para implementar el retraso; en este caso, ¿puedo tener un ciclo que transcurra el tiempo de entrada y luego ignorar el tiempo transcurrido por mi ciclo de visualización?
Aaron
1
@AaronGOUZIT Permitiré eso, siempre y cuando sea coherente: los intervalos de tiempo entre los momentos en que su programa comienza a imprimir una línea son tomados del usuario, O los tiempos de espera entre el final de la impresión de una línea y el comienzo de la impresión. los siguientes son todos tomados del usuario.
Zgarb
1
@TessellatingHeckler El último; ver la sesión de ejemplo.
Zgarb
1
@KritixiLithos Solo utilicé mi mano derecha yum yum, lo cual fue bastante engorroso.
Zgarb

Respuestas:

15

CJam, 45 41 39 36 34 bytes

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

Esto no tiene sentido en el intérprete en línea, por supuesto, pero funciona en el intérprete de Java.

No muestra un aviso.

Explicación

{        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.
}/
Martin Ender
fuente
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]))

Con la esperanza de encontrar un par de bytes más para recortar.

Mwr247
fuente
1
Podrías guardar un par de bytes con j=i=[]++todavía funcionará!) También, ¡tu whileno es necesario !=''ya que es falso! ¡Tan decepcionado que me perdí map! +1
Dom Hastings
1
Buena nota sobre el !=''. Me preocupaba si la entrada era 0, pero parece manejar eso bien. Había notado la []posibilidad de incremento antes, pero había sido tonto e intenté hacerlo j++. Haciendo ++jtrabajos, ya []++que aparentemente es 0 XD ¡Gracias!
Mwr247
1
Marque esto el día que supe que había do...whilebucles en JS
Conor O'Brien
6

JavaScript, 120 bytes

No hay posibilidad de acercarse a CJam con este enfoque, sino un guión sencillo.

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)}
Dom Hastings
fuente
1
Parece que ambos fuimos por JS al mismo tiempo jaja, aunque obtuviste el tuyo un poco antes que el mío. Aún así, diferentes enfoques.
Mwr247
@ Mwr247 ¡Sin embargo, el tuyo es más elegante!
Dom Hastings
6

Pyth, 68 bytes

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

Se desperdicia muchos bytes en la llamada a sleep, ya que Pyth no tiene sleepfunción.

kirbyfan64sos
fuente
3
Tal vez deberías sugerir eso como una adición a Pyth.
mbomb007
Creo que tiene un error off-by-one en la espera. Intente iniciar el programa, espere, escriba algo y presione Intro dos veces rápidamente. Imprimirá inmediatamente la primera línea, luego esperará un momento antes de terminar.
FryAmTheEggman
6

Rubí, 74

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

Trucos: *aen la primera línea se inicializa una matriz vacía. Podría usar $*en su lugar, pero es un poco incompleto ya que está lleno de algunas invocaciones y solo me ahorra un byte. $/es una nueva línea y $_es la última línea recuperada por gets.

Editar: Dormir al final cuesta 20 bytes más, probablemente una forma de jugar golf

t,*a=Time.now
a<<[$_,t-t=Time.now]while$/<gets
t-=Time.now
a.map{|l,i|sleep -i;puts l}
sleep -t
histocrat
fuente
Creo que necesita dormir en la última línea, dependiendo de cuánto tiempo le tomó al usuario proporcionar una línea vacía.
Konrad Borowski
Para dormir al final (solución 2), llama Time.nowsuficientes veces que usando def n;Time.now;end, guardando un total de 2 bytes
Value Ink
6

Pitón 3, 124

Solo funciona en 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:]]

Mantener la entrada y los tiempos en listas separadas me costó 3 bytes más . Probablemente no sea el mejor enfoque.

Una versión amigable de 129 bytes de Unix, con crédito a 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:]]
FryAmTheEggman
fuente
¿No puedes usar en time()lugar de clock()guardar 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)).

Probablemente hay mucho para jugar golf aquí, pero esto servirá por ahora ...

Fatalizar
fuente
4

PowerShell, 261 190 121 95 Bytes

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

Atrezzo a TessellatngHeckler y tomkandy por la asistencia e inspiración en el golf.

Esto es muy similar en concepto a la versión de 121 bytes a continuación, solo estamos creando y construyendo dinámicamente una lista de objetos, en lugar de pasar por un ciclo while para almacenarlos en una matriz explícita $a. En ambos casos, esa lista de objetos se canaliza al mismo bucle foreach |%{...}. La indexación en el selector de matriz de resultados ($b=!$b+!$_)está formulada esta vez para eliminar la if($_){$_}de las siguientes iteraciones, lo que ahorra unos pocos bytes más.


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

Ampliado y 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
}

Anterior er, 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)}

¡Santa verbosidad, Batman! Vamos a desglosarlo:

$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)
}
AdmBorkBork
fuente
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 Gracias! Actualizado con mejoras.
AdmBorkBork
@TessellatingHeckler Excelente! Estaba luchando con una forma de controlar la alternancia de manera efectiva, e indexar en una matriz como esa es la opción obvia ahora que lo veo. Por cierto, jugué otro byte al eliminar el @de esa matriz, ya que no es necesario en este contexto, así que hasta 121 .
AdmBorkBork
@TimmyD lo que intentaba ayer fue poner ($ t, $ l) pares en $ a haciendo una matriz anidada. No pude hacerlo funcionar, pero hoy sí pude y ayuda un poco porque no hay necesidad de alternar, solo lea cada par y úselos. Entonces me di cuenta: tenemos una tubería perfectamente buena que puede hacer cola, ¿por qué mantener una matriz? $($l=1;while($l){Measure-Command{$l=read-host};$l})|%{($_,(sleep -m($_.Ticks/1e4)))[($b=!$b+!$_)]}- y con un cambio en la palanca, de modo que cuando la cadena está vacía no se alterna y duerme en su lugar - 98
TessellatingHeckler
(Hazlo un do{...}while($l) bucle y suelte $l=1;para obtener 95 )
TessellatingHeckler
3

Perl 6, 70 caracteres

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

El intérprete de Perl 6 solo define tres variables simbólicas (a diferencia de la locura de Perl 5). Para ser exactos, $/, $!, y $_. Este programa los usa todos, para evitar el costo de declarar variables usando my.

getlee una línea de STDIN. No contiene una nueva línea, a diferencia de Perl 5.

nowincorporado devuelve una hora actual. Cuando se resta, da un intervalo que se puede pasar a una cadena.

Un método sin nada a la izquierda (como .pushy .mapen este código) funciona $_.

Usando el repeat whilebucle (conocido como do whileen otros lenguajes de programación), Perl 6 escribe la marca de tiempo actual $/y empuja la línea recibida (que también almacena $!) y la diferencia entre la hora actual y la marca de tiempo $/. Debido al orden de los parámetros, nowno se calcula hasta que se recibe una línea.

La whilecondición verifica si la línea no está vacía (en Perl 6, "0"es un valor verdadero, a diferencia de Perl 5).

Después de obtener todas las marcas de tiempo y líneas, solo proporciono las de mapdevolución de llamada que duerme un poco y dice lo que se dijo.

Konrad Borowski
fuente
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.

Versión sin golf:

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)
}
un espagueti
fuente
2

JavaScript (ES6) 102

Reuniendo los esfuerzos de Mwr247 y 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>

revs edc65
fuente
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

Y sin golfos:

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

Esto no será 100% preciso en el tiempo, ya que no tiene en cuenta el tiempo necesario para mostrar cada cadena, pero eso debería ser bastante rápido, por lo que el tiempo debería ser bastante cercano.


Después de una rápida revisión, he guardado algunos bytes al eliminar la matriz de celdas profundas de doble capa. Resulta que todo lo que necesitaba era ;conseguir que se dividiera correctamente al empacar.

Tom Carpenter
fuente
1
Tal vez podrías hacer una versión de golf en MATL.
ckjbgames
1

Java, utilizando la versión 1.04 de esta 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);}}}
SuperJedi224
fuente
1

Caché ObjectScript, 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 de costumbre, esto supone una tabla de símbolos limpia antes de ejecutarse d r.

Este problema no se puede resolver en ANSI MUMPS, ya que el estándar ANSI solo requiere una resolución de segundo nivel por el tiempo intrínseco $H[OROLOG]. Afortunadamente, Intersystems Caché, que actualmente es la plataforma líder de la industria para MUMPS, proporciona la implementación $ZT[IME]S[TAMP]intrínseca definida , que proporciona una resolución de nivel de microsegundos.

(La puntuación era anteriormente de 105 bytes, pero había un error).

senshin
fuente
1

C ++ 11, 343 338 bytes

Quería ver cuántos bytes necesitaría un código para eso en c ++. Mucho más de lo que esperaba. Quizás he complicado demasiado la solución.

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

Veamos si puedo reducir esto de alguna manera.

Wendelbsilva
fuente
Puede eliminar los espacios en #includes y la declaración de tipo para main. Eso es 7 bytes, no mucho, pero un comienzo. También puede usar en autolugar de stringpara s.
Alex A.
Gracias por la respuesta. Mantendré el tipo de retorno para el principal. Si no recuerdo mal, solo para ceso no tenemos que especificarlo. Inicialmente intenté usar auto s... pero parece que está convertido const char *y no std::string. Me pregunto si puedo crear un alias para while.
wendelbsilva
Eliminar el tipo de retorno funciona para C ++ aunque "no debería" según el estándar. Puede intentar crear un alias para whileusar un #definetal vez.
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

Esto crea un archivo temporal t. Sobrescribirá un archivo existente con el mismo nombre.

La idea en sí es bastante corta, pero tratar con caracteres especiales en la entrada agrega alrededor de 15 bytes ...

Dennis
fuente
1

VBA, 233 228bytes

Estoy seguro de que se puede jugar mucho al golf. no especificaron cuántas entradas, así que codifiqué las longitudes de mi matriz porque es más corta que entonces Redim preserve.

La entrada es a través de una ventana emergente, la salida se debug.printdebe a que msgboxproduce un MODAL y detiene el código.

No sé cómo probar si esto es preciso para los 0.01s. Tal vez alguien pueda probar, pero le doy al comando de espera el número de una manera que DEBE usar los milisegundos, pero VBA no es conocido por hacer lo que debería.

El If gotopuede ser sustituido por un bien golfizado 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

No funcionará en Access VBA, porque el acceso no tiene un comando de espera porque Microsoft odia la coherencia

JimmyJazzx
fuente
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

Creo que esto podría hacerse un poco más corto.

12Me21
fuente
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++;}}

Detallado

#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;
}
Khaled.K
fuente