复制文件-Windows风格


40

这个挑战是受xkcd启发的:

在此处输入图片说明

挑战:

您将模拟复制大文件(1 GB)。传输速率将在10 kB /秒到100 MB /秒之间变化。您的任务是输出文件传输的剩余时间。输出应如下所示:

Time remaining: 03:12    (meaning it's 3 minutes and 12 seconds left)
Time remaining: 123:12   (meaning it's 2 hours, 3 minutes and 12 seconds left)
Time remaining: 02:03:12 (optional output, meaning the same as above)

前导零不需要在分钟和小时内显示(可选),而必须显示几秒钟。仅用秒显示剩余时间是不正确的。

文件传输:

  • 传输速率将从10 MB /秒开始。
  • 每秒传输速率将有30%的机会发生变化
  • 新的传输速率应[10 kB/s, 100 MB/s]在10 kB / s 的范围内随机选择(均匀分布)。

注意:您实际上不需要复制文件。

您可以选择使用:1 GB = 1000 MB, 1 MB = 1000 kB, 1 kB = 1000 B1 GB = 1024 MB, 1 MB = 1024 kB, 1 kB = 1024 B

输出:

  • 您开始01:40不是01:39
  • 显示传输速率更改之后但以该速率传输任何内容之前的时间
  • 秒应该显示为整数,而不是小数。向上/向下/最接近是可选的。
  • 除非用您的语言无法做到,否则您应该每秒清除屏幕一次。
  • 输出应该是恒定的:Time remaining: 00:00文件传输结束时。

例:

我将所有小数点后的时间取整。假设以下各行之间的间隔为1秒,并且每行之间的屏幕均被清除:

Time remaining: 01:40  (Transfer rate: 10 MB/s)
Time remaining: 01:39      1 GB - 10 MB
Time remaining: 01:38      1 GB - 2*10 MB
Time remaining: 01:37      1 GB - 3*10 MB
Time remaining: 01:28:54   1 GB - 4*10 MB  (TR: 180 kB/s)
Time remaining: 01:28:53   1 GB - 4*10 MB - 180 kB
Time remaining: 01:28:52   1 GB - 4*10 MB - 2*180 kB  
Time remaining: 00:13      1 GB - 4*10 MB - 3*180 kB  (TR: 75 MB/s)
Time remaining: 00:12      1 GB - 4*10 MB - 3*180 kB - 75 MB
Time remaining: 00:11      1 GB - 4*10 MB - 3*180 kB - 2*75 MB
Time remaining: 00:10      1 GB - 4*10 MB - 3*180 kB - 3*75 MB
Time remaining: 00:09      1 GB - 4*10 MB - 3*180 kB - 4*75 MB
Time remaining: 00:08      1 GB - 4*10 MB - 3*180 kB - 5*75 MB
Time remaining: 14:09:06   1 GB - 4*10 MB - 3*180 kB - 6*75 MB  (TR: 10 kB/s)
Time remaining: 14:09:05   1 GB - 4*10 MB - 3*180 kB - 6*75 MB - 10 kB
Time remaining: 00:06      1 GB - 4*10 MB - 3*180 kB - 6*75 MB - 20 kB  (TR: 88.110 MB/s)
Time remaining: 00:05
Time remaining: 00:04
Time remaining: 00:03
Time remaining: 00:02
Time remaining: 00:01
Time remaining: 00:00     <- Transfer is finished. Display this.

1
您应该将XKCD工具提示文本放在图像下方。节省了人们不得不自行查找的时间。
mbomb007 '17

6
@ mbomb007,将鼠标悬停在图片上:)
Stewie Griffin

应该是“您从1:40(或1:42)开始(或)而不是1:39(或1:41)开始”吗?
乔纳森·艾伦

另外,如果我们使用的是1024版本,应该使用什么步长?
乔纳森·艾伦

如果剩余小时数为零,我们可以00:00:10例如保留输出吗?
AdmBorkBork

Answers:


9

Pyth- 70 68字节

K^T5J^T3W>KZ%." r3úBTê;¥
í".D/KJ60=J?<OT3O^T4J=-KJ.d1.

无需睡眠即可在线尝试


@DigitalTrauma对不起,正在使用路易斯的答案作为指导。
Maltysen '17

@DigitalTrauma已修复。
Maltysen '17

6
大声笑。当从(高尔夫)语言A移植到(高尔夫)语言B比阅读规范更容易时;-)
Digital Trauma '02

@Maltysen抱歉!:-)
路易斯·门多

2
您能解释一下这里到底发生了什么吗?
恢复莫妮卡

8

PowerShell中190个 215 187字节

($t="Time remaining: ")+"00:01:42";for($f,$r=1gb,10mb;$f-gt0;$f-=$r){if((Random 10)-lt3){$r=(Random -mi 1kb -ma (10mb+1))*10}$t+[Timespan]::FromSeconds([int]($f/$r));sleep 1}$t+"00:00:00"

在线尝试!(TIO不支持清除行之间的屏幕)

将我们的初始文件$f大小和初始传输速率分别设置$r1gb10mb/ s。然后,只要我们还有$f余数,我们就会循环。

在循环内,if选择从0到的数字9,如果是0、1或2(即30%的时间),我们将更改速率。这会在之间选择一个随机整数1kb10mb然后将其乘以10得到我们的步数。

然后,我们充分利用FromSeconds 静态方法TimeSpan.NET库构建的剩余时间。该调用的输出格式与挑战要求完全匹配,因此不需要其他格式。

(通过@ConnorLSW保存了一堆)


1
@StewieGriffin TIO具有输出缓存。在“设置”抽屉中选择“禁用输出缓存”,它将得到不同的结果。
TheBikingViking

也许我错过了一些东西,但-f操作员似乎什么也没做。通过取出并使用forloop而不是while,然后将两个实例都更改get-datedate,我可以节省22个字节。在线尝试!
briantist

@briantist TIO要求,Get-Date因为否则它使用Linux date命令,这是不同的。您可以将其放在Windows上,因为PowerShell会包装Windows date命令。但是,感谢您的for循环构建!
AdmBorkBork '17

@AdmBorkBork是的,我注意到了,但是在普通的Windows环境中它可以工作。我想只nal date get-date在TIO中放入标题是否可以接受?
briantist

@AdmBorkBork并在Windows上没有包装Windows date命令,它只是忽略了它,因为它不是Windows上的.exe,因此它会退回为与之相同的行为randomget-如果所有其他命令均失败,请尝试使用带前缀的命令)。
briantist

5

MATL,78字节

感谢@Maltysen@DigitalTrauma的更正。

1e5 1e3`XK10&XxyXIy/t0>*12L/'MM:SS'XO'Time remaining: 'whD-r.3<?1e4Yr}K]I0>]xx

MATL在线上尝试一下(如果最初不起作用,则可能需要多次按“运行”)。

在线口译员在30秒后超时。您可能需要更改10(以十分之一秒为单位的暂停时间),例如,3以提高显示速度

说明

1e5                  % Push 1e5: file size in 10-kB units
1e3                  % Push 1e3: initial rate in 10-kB/s units
`                    % Do...while
  XK                 %   Copy current rate into clipboard K (doesn't consume it)
  10&Xx              %   Wait 1 second and clear screen
  y                  %   Duplicate current file size onto the top of the stack
  XI                 %   Copy it to clipboard I (doesn't consume it)
  y                  %   Duplicate current rate onto the top of the stack
  /                  %   Divide. This gives the estimated remaining time in seconds
                     %   It may be negative in the last iteration, because the
                     %   "remaining" file size may have become negative
  t0>*               %   If negative, convert to 0
  12L/               %   Push 86400 and divide, to convert from seconds to days
  'MM:SS'XO          %   Format as a MM:SS string, rounding down
  'Time remaining: ' %   Push this string
  wh                 %   Swap, concatenate
  D                  %   Display
  -                  %   Subtract. This gives the new remaining file size
  r                  %   Push random number uniformly distributed in (0,1)
  .3<                %   Is it less than 0.3?
  ?                  %   If so
    1e4Yr            %     Random integer between 1 and 1e4. This is the new rate 
                     %     in 10-kB/s units
  }                  %   Else
    K                %     Push rate that was copied into clipboard K
  ]                  %   End
  I                  %   Push previous remaining file size from clipboard I
  0>                 %   Is it positive?
]                    % End. If top of the stack is true: next iteration
xx                   % Delete the two numbers that are on the stack

我不了解MATL,但在我看来,您似乎总是得到一个新的汇率,而不是从您的解释中仅获得30%的时间。
Maltysen'2

@Maltysen现在纠正。感谢您的单挑!
路易斯·门多

@DigitalTrauma现在已纠正
Luis


4

Bash +通用工具,117

简单实施。除以10000可节省几个字节:

for((b=10**5,r=1000;b>0;r=RANDOM%10<3?RANDOM%10000+1:r,b-=r));{
clear
date -ud@$[b/r] "+Time remaining: %T"
sleep 1
}

在线尝试sleep 0在TIO上使用,因此您不必等待。 clear在TIO上不起作用。


3

JavaScript(ES6),162个字节

以分钟为单位显示分钟,以填充秒为单位(已淹没)

例如, 123:45

t=1e5
s=1e3
setInterval(c=>c.log(`Time remaining: ${c.clear(d=t/s),d/60|0}:`+`0${t-=s>t?t:s,r=Math.random,s=r()<0.3?1+r()*1e4|0:s,d%60|0}`.slice(-2)),1e3,console)


我认为您忘了缩短console.clearc.clear
ETHproductions's

@ETHproductions糟糕!谢谢:)
乔治·里斯

您可以通过添加HTML-- <input id=o>并进行一些其他调整将其减少到154个字节:t=1e5;i=s=1e3;setInterval(_=>o.value=`Time remaining: ${(d=t/s)/60|0}:`+`0${t-=s>t?t:s,r=Math.random(),s=r<.3?1+r*1e4|0:s,d%60|0}`.slice(-2),i)
粗野的

2

蟒3.6(212 203个字节)

from random import*
import time,datetime
r=1e7
d=1e9
while 1:
 print(f"\x1b[KTime remaining: {datetime.timedelta(seconds=d//r)}",end="\r");d=max(0,d-r);time.sleep(1)
 if random()>.7:r=randint(1,1e4)*1e4

我认为非常简单。使用ANSI转义序列和K命令擦除行。


1
使用跳过第一行中的空格from random import*d//r比短int(d/r)。同样,不妨r=1e7;d=1e9从一开始就考虑。
价值墨水

@ValueInk对,我没有想到r和d是1eX,因为我希望它们是整数。当我缩短了randint行了,我忘了这一点... :)
乔纳斯·舍费尔

1

批次,193个字节

@set/ap=10000,s=p*10,r=p/10
:l
@set/at=s/r,m=t/60,n=t%%60+100,s-=r
@cls
@echo Time remaining: %m%:%n:~1%
@timeout/t>nul 1
@if %random:~-1% lss 3 set/ar=%random%%%p+1
@if %t% gtr 0 goto l

注意:偏向27.68 MB / s或更低的速率。


1

ç 184 171 155字节

f(){i,j=0,r=1e7;for(i=1e9;i>0;i-=r){j=i/r;printf("Time remaining: %02d:%02d:%02d\r",j/3600,(j/60)%60,j%60);sleep(1);if(rand()%10<3)r=(rand()%10000)*1e4;}}

我希望这符合条件。

非高尔夫版本:

void f()
{
    int j=0;
    float rate=1e7; 
    for(int size=1e9;i>0; size-=rate)
    {     
       j=size/rate;      
       printf("Time remaining: %02d:%02d:%02d\r",j/3600,(j/60)%60,j%60);
       sleep(1);

       if(rand()%10<3)
          rate=(rand()%10000)*1e4;          



   }

}

说明:在高尔夫版本中,i对应size于非高尔夫版本,rrate在非高尔夫版本中。j以秒为单位存储剩余时间。

  • 我有10 ^ 9字节要复制。我开始以每秒10 MB的速度进行复制,
  • 如果概率小于30%,请更改速率(从10 KB更改为每秒100 MB)

@ValueInk感谢您节省13个字节。

@ nmjcman101感谢您保存16个字节。


这看起来并不像挑战所说明的那样。您能解释一下它是如何工作的吗?
价值墨水

它只是模拟时间输出,我还没有弄清楚如何做数据传输部分。猜猜我要等到那时。
亚伯汤姆

3次迭代后,您无需更改速率。它有30%的更改机会。因此,您可能想要执行以下操作:(if(rand()%10<3)r=(rand()%10000+1)*1e4;特别是因为最低速率为10 kB / s,而不是您的解决方案所说的1MB / s,并且速率几率应该是一个均匀的分布。)
Value Ink

@ValueInk非常感谢。:) 更新。完成工作!我不知道如何精确模拟30%的概率部分。现在要清楚得多。
亚伯汤姆

您可以和 (20 j/3600,(j/60)%60,j%60)一起打高尔夫球(21)s=60;j/s/s,j/s%s,j%s
戴维
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.