时间敏感的回声


38

背景

echo程序是如此整洁。您可以说任何话,并且每次都能完美地重复您的话!多么酷啊!令人失望的是,无论您的键入速度如何,它都会一次全部重复输入,这不太现实。我们必须解决该问题。

任务

您的程序应从STDIN或最接近的等效项获取其输入。它应一一读取用户的行,可能显示一些提示,直到他们输入空行。此后,它将按照给定的顺序将行打印到STDOUT或最接近的行。最后(空)行不会打印,最后一个打印行不需要尾随换行符。

此外,程序应保留每行之间的时间间隔:如果用户花了x几秒钟进入一行,则它应花费x该程序几秒钟来打印它。这也适用于第一行和最后一行;空行不会被打印,但是程序仍然要等待终止。

这是该程序的示例会话。所有不产生文本的操作均在方括号中描述,(可选)提示显示为>

[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]

没有动作,会话看起来像这样:

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

规则和计分

等待时间应精确到0.01秒以内(实际上,如果普通人无法分辨出差异,您就可以了)。最低字节数获胜,并且不允许出现标准漏洞。如果您的语言具有恰好可以完成此任务的内置功能,则可能无法使用它。


9
下一步:打一个玩基本节奏游戏的程序:P
Sp3000

我们可以忽略程序输出字符所花费的时间吗?我的意思是,如果我可以衡量我的语言输出一个字符需要0.1秒,我应该考虑到它吗?全面披露,我打算使用> <>口译员的答辩时间来实施延迟;在这种情况下,我可以让一个循环跳过输入时间,然后忽略显示循环所经过的时间吗?
亚伦

1
@AaronGOUZIT我会允许的,只要您保持一致:程序开始打印行的那一刻之间的时间间隔都是从用户那里获取的,或者从完成打印行到开始打印之间的等待时间是接下来的全部取自用户。
Zgarb 2015年

1
@TessellatingHeckler后者;请参阅示例会话。
Zgarb 2015年

1
@KritixiLithos我只用了右手yum yum,这很麻烦。
Zgarb 2015年

Answers:


15

CJam,45 41 39 36 34字节

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

当然,这在在线解释器中并没有真正的意义,但是在Java解释器中有效。

它不显示提示。

说明

{        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,119112字节

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

希望找到更多的字节来删除。


1
您还可以使用j=i=[]++仍然可以使用!)保存几个字节,while而且不需要,!=''因为它是虚假的!太失望了我错过了map!+1
Dom Hastings

1
请注意!=''。担心输入是否为0,但似乎可以解决问题。我之前曾注意到这种[]增加的可能性,但是我一直很愚蠢,并试图做到j++这一点。正在++j工作,因为[]++显然是0 XD谢谢!
Mwr247

1
纪念这一天,我得知有do...while在JS循环
康纳尔奥布莱恩

6

JavaScript,120字节

用这种方法没有机会接近CJam,而是一个简单的脚本。

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
似乎我们俩都同时去了JS哈哈,尽管您早于我。尽管如此,不同的方法。
Mwr247

@ Mwr247的确,您的却更加优雅!
唐·黑斯廷斯

6

Pyth,68个字节

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

由于Pyth没有功能,因此在对的调用上浪费了很多字节。sleepsleep


3
也许您应该建议将其作为Pyth的补充。
mbomb007

我相信您在等待中遇到一个错误。尝试启动程序,等待,然后输入一些内容,然后快速按两次Enter键。它将立即打印第一行,然后等待一会儿再终止。
FryAmTheEggman

6

Ruby,74岁

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

技巧:*a第一行会初始化一个空数组。我可以改用$*它,但是它有点粗略,因为其中填充了一些调用,只为我节省了一个字节。$/是换行符,$_是检索到的最后一行gets

编辑:睡到最后要多花20个字节,这可能是打败它的一种方法

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

我认为您需要睡在最后一行,具体取决于用户提供空行的时间。
Konrad Borowski

对于末睡(溶液2),你可以调用Time.now足够的时间,使用def n;Time.now;end,节省了整整2个字节
价值油墨

6

Python 3、124

仅适用于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:]]

将输入和时间保存在单独的列表中会使我花了3个字节。可能不是最好的方法。

129字节Unix友好版本,由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:]]

您不能使用time()而不是clock()保存2个字节吗?
kirbyfan64sos

4

SWI-Prolog,185个字节

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

这里可能有很多高尔夫运动,但是现在就可以了。


4

PowerShell中,261 190 121 95个字节

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

TessellatngHecklertomkandy的高尔夫协助和灵感支柱

这在概念上与下面的121字节版本非常相似,我们只是动态创建和构建对象列表,而不是通过while循环将它们存储到显式数组中$a。在这两种情况下,该对象列表都通过管道传递到相同的foreach循环中|%{...}。这次($b=!$b+!$_)制定了对结果数组选择器的索引,以消除if($_){$_}下面的迭代,从而节省了更多的字节。


上一页,121字节

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

扩展并解释:

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

上一个190字节

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
}

上一个261字节

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

神圣的冗长,蝙蝠侠!让我们分解一下:

$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谢谢!更新了改进。
AdmBorkBork 2015年

@TessellatingHeckler太好了!我正在努力寻找一种有效控制交替的方法,现在看来,索引到这样的数组是显而易见的选择。顺便说一句,我通过@从数组中删除来打高尔夫球的另一个字节,因为在这种情况下不需要它,所以降至121
AdmBorkBork 2015年

@TimmyD我昨天要尝试的是将($ t,$ l)对放入$ a中,从而形成一个嵌套数组。我无法使其工作,但是今天我可以并且它有所帮助,因为无需切换,只需阅读每一对并使用它们即可。然后我意识到-我们有一个非常好的管道可以排队,为什么要保留一个数组呢?$($l=1;while($l){Measure-Command{$l=read-host};$l})|%{($_,(sleep -m($_.Ticks/1e4)))[($b=!$b+!$_)]}-并且更改了切换,因此当字符串为空时,它不会切换,而是
TessellatingHeckler 2015年

do{...}while($l)循环播放并下降$l=1;95
TessellatingHeckler,2015年

3

Perl 6,70个字符

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

Perl 6解释器仅定义了三个符号变量(与Perl 5的疯狂不同)。确切的说,$/$!,和$_。该程序全部使用了它们,从而避免了使用声明变量的开销my

get从STDIN读取一行。与Perl 5不同,它不包含换行符。

now内置返回当前时间。减去时,它给出可以传递给字符串的间隔。

在其左侧不带任何内容的方法(如.push.map在此代码中)适用于$_

使用repeat while循环(do while在其他编程语言中称为),Perl 6将当前时间戳写入$/,并将接收到的行(也存储到$!)推入,并将当前时间与时间戳之间的时差压入$/。由于参数顺序,now直到接收到一行才计算。

while条件检查行是否不为空(在Perl 6中"0"为真值,与Perl 5不同)。

在获得所有时间戳记和所有行之后,我仅将其提供给map回调方法,该方法会睡一会儿并说出所讲的内容。


2

Groovy,202个字节

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

基。

非高尔夫版本:

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

集中Mwr247和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

和无高尔夫球场:

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

这不会在时间上精确到100%,因为它没有考虑显示每个字符串所花费的时间,但是应该很快,因此在时间上应该非常接近。


快速浏览后,我通过删除双层深单元数组节省了一些字节。事实证明,我需要做的;只是使它在包装时能正确拆分。


1
也许您可以制作MATL打高尔夫球的版本。
ckjbgames

1

Java,使用该库的 1.04版,385个字节

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

CachéObjectScript,123字节

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

像往常一样,这假设在运行之前有一个干净的符号表d r

在ANSI MUMPS中无法解决此问题,因为ANSI标准仅要求时间固有的二级分辨率$H[OROLOG]。幸运的是,IntersystemsCaché(目前是MUMPS的行业领先平台)提供了实现定义的$ZT[IME]S[TAMP]内在函数,它提供了微秒级的分辨率。

(分数以前为105个字节,但存在一个错误。)


1

C ++ 11,343 338字节

想要查看c ++中的代码需要多少字节。比我预期的要多得多。也许我使解决方案复杂化了。

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

让我们看看是否可以减少这种情况。


您可以删除#includes 中的空格和的类型声明main。这是7个字节-不多,只是一个开始。您也许还可以使用auto而不是string用于s
Alex A.

感谢您的反馈。我将保留主要的返回类型。如果我没记错的话,仅此而已,c不必指定它。我最初尝试使用auto s...,但看起来它转换为const char *而不是std::string。我想知道是否可以为创建别名while
wendelbsilva

删除返回类型适用于C ++,即使按照标准“不应”也是如此。你可以尝试创建一个别名while使用#define可能。
Alex A.

1

Bash,91个 90字节

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

这将创建一个临时文件t它将覆盖具有相同名称的现有文件。

这个想法本身很短,但是在输入中处理特殊字符会增加大约15个字节...


1

VBA,233个 228bytes

我确定这可以打很多球。他们没有指定输入多少,所以我硬编码了数组的长度,因为它比数组短Redim preserve

输入是通过弹出窗口,输出是debug.print因为msgbox生成MODAL并暂停代码。

我不知道如何测试是否精确到0.01秒。也许有人可以测试,但是我以应该使用毫秒的方式给wait命令编号,但是VBA并没有以应做的方式而闻名。

If goto可能能够通过公golfed被取代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

在Access VBA中将无法使用,因为Microsoft讨厌一致性,因此访问没有等待命令


0

SmileBASIC,122字节

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

我认为这可以缩短一点。


0

C UNIX,272个字节

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

详细

#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;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.