Ho浩时间单位


40

在弗诺·温格(Vernor Vinge)的出色且引人入胜的书《天空中的深处》 (顺便提一下,我强烈推荐1)中,跨越各种恒星系统的文化“ Ho何 ”没有“天”,“月”,“ ”等,因此具有独特的计时系统,可以完全以秒为单位测量时间。最常用的单位是Ksec(毫秒),Msec (兆秒)和Gsec(千兆秒)。这是我自己的书本中的一个方便的图表(由于无法在线查找):

方便的图表

您目前正乘坐Pham Nuwen飞机飞行,并且刚刚收到来自一个陌生的未知行星“ 地球 ” 的消息。2它们使用的时间单位与您使用的时间单位不同,并且您的计算机无法识别它们的时间单位。作为船舶的常驻程序员-考古学家,您的工作是打补丁时间处理代码,以便它可以识别地球的时间单位。

自然,由于您只剩下了几Ksec的时间才进入冷睡眠状态,因此您希望使代码尽可能短,以便可以快速编写。幸运的是,作为星际贸易文化,Qeng Ho可以使用每一种发明的编程语言。

输入项

输入将是一个包含一个或多个用空格分隔的组件的单个字符串 。甲组件被定义为一个整数> 0且≤255,然后一空间,然后之一secondminutehourdayweekmonthyeardecade,或century,可能有多个(具有添加的s,或者 centuries在过去的情况下)。

以下是一些有效的示例输入:

10 days 12 hours
1 year
184 centuries 1 second
9 weeks 6 days 2 hours 1 minute 20 seconds

您可以对输入假设以下内容:

  • 复数单位将始终与相关数量一致。

  • 如果输入中包含多个分量,则它们将始终按长度降序排列。

对于此挑战,以下是各种输入单位的含义:

unit     relative    absolute
---------------------------------------
second   1 second    1 second
minute   60 seconds  60 seconds
hour     60 minutes  3600 seconds
day      24 hours    86400 seconds
week     7 days      604800 seconds
month    30 days     2592000 seconds
year     365 days    31536000 seconds
decade   10 years    315360000 seconds
century  10 decades  3153600000 seconds

输出量

以下是您的代码必须支持的Qeng Ho单位:

unit    relative      absolute
----------------------------------------
second  1 second      1 second
Ksec    1000 seconds  1000 seconds
Msec    1000 Ksecs    1000000 seconds
Gsec    1000 Msecs    1000000000 seconds

使用以下算法确定代码的输出:

  • 首先,将输入代表的总时间相加。

  • 找到更短的时间或与输入时间相同的最大Qeng Ho单位-本质上,找到至少一个存在的最大Qeng Ho单位。

  • 将输入中给出的总时间转换为该单位,然后输出结果,四舍五入到小数点后三位。

您可以选择使用以下哪种方法:向上舍入,向下舍入,从零舍入或向∞或-∞舍入。如果四舍五入的结果以结尾0,则可以删除尾随零或保留所需的任意多个(或同时输入两个,具体取决于输入)。

如果舍入的结果是完全1.000,你必须使用单数形式(secondKsecMsecGsec); 否则,可使用复数形式(secondsKsecsMsecsGsecs)。

在某些边缘情况下,您可能使用的单位是例如Ksec,但是获得的舍入结果为1000.000 Ksecs。在这种情况下,您可以简单地输出 1000.000 Ksecs而不是1 Msec

您可能总是假设输入的单位是降序(世纪,十年,年份等);此外,在任何给定单位之后的组件将总是更短(即,1 decade 20 years无效输入)。

测试用例

注意:*由于四舍五入的差异,带有星号()的结果可能相差不大。

input                                         output
-------------------------------------------------------------
1 hour                                        3.600 Ksecs
1 day                                         86.400 Ksecs
2 weeks                                       1.210 Msecs
1 year                                        31.536 Msecs
32 years                                      1.009 Gsecs   *
1 second                                      1.000 second
1 century 6 decades                           5.046 Gsecs   *
255 centuries                                 804.168 Gsecs
2 weeks 6 days 1 hour 19 minutes 4 seconds    1.733 Msecs
1 week 3 days 3 hours 7 minutes               875.220 Ksecs
1 week 4 days 13 hours 46 minutes 40 seconds  1.000 Msec
2 months 2 hours                              5.191 Msecs   *
16 minutes 39 seconds                         999.000 seconds

规则

  • 这是,因此以字节为单位的最短代码获胜。

1:当然,只有喜欢硬科学幻想曲的人 在这种情况下,我建议先阅读《深渊之火》,这(我认为)更加奇妙。

2:好吧,从技术上讲,《天空的深处》曾多次提到“旧地球” ,但是...


测试用例9似乎不正确(请参见我的回答)
edc65

1
这艘船不知道地球时间,但是对所有地球编程语言都有全面的了解。很合逻辑。</ sarcasm>
拍手

2
Dang,我使用内置的单元支持获得了一个非常简短的Mathematica解决方案,但是它的解释2 months 2 hours是“ 2个月* 2小时”。
2012rcampion 2015年

1
嗯,我注意到这些因素看起来很奇怪,就像过时的时间处理功能中的那些因素一样,没人会在许多这类语言中使用它们。
Random832

Answers:


6

APL(Dyalog APL) 157 156 154 151 154 141 142字节

{∊(3⍕N)' '((B/S⊃' KMG')'sec','ond'/⍨~B←T≥1E3),'s'/⍨1≠N←T÷1E3*S←⌊1E3⍟T←+/×/↑⍎¨'\d+ .a?i?'⎕S'&'⊢⍵⊣c←10×d←10×⊃y m w←365 30 7×da←24×h←×⍨mi←60×s←1}

感谢ngn削减了13个字节。

必须具有⎕IO←0,这是许多APL中的默认设置。

在线尝试!


如果将1E3分配给名称(如z),则在第一个实例中您浪费了两个字符,在第二个实例中您已经保存了一个字符,从第三个实例开始,您就保存了两个字符。是不是
lstefano

@lstefano不,第一个将花费4:⌊1E3⍟⌊(z←1E3)⍟,然后在每个下一个保存2 1E3z
亚当

是的,绝对正确。鉴于只有3个,没有收益。对不起,噪音。
lstefano

6

JavaScript(ES6)255

f=s=>(s=s.replace(/(\d+) (..)/g,(_,n,u)=>t+={se:1,mi:60,ho:3600,da:86400,we:604800,mo:2592e3,ye:31536e3,de:31536e4,ce:31536e5}[u]*n,t=0),[a,b]=t>=1e9?[t/1e9,' Gsec']:t>=1e6?[t/1e6,' Msec']:t>999?[t/1e3,' Ksec']:[t,' second'],a.toFixed(3)+b+(a-1?'s':''))  

// test

console.log=x=>O.innerHTML+=x+'\n'

;[
 ['1 hour','3.600 Ksecs']
,['1 day','86.400 Ksecs']
,['2 weeks','1.210 Msecs']
,['1 year','31.536 Msecs']
,['32 years','1.009 Gsecs'] 
,['1 second','1.000 second']
,['1 century 6 decades','5.046 Gsecs']
,['255 centuries','804.168 Gsecs']
,['2 weeks 6 days 1 hour 19 minutes 4 seconds','1.733 Msecs']
,['1 week 3 days 3 hours 7 minutes','875.220 Ksecs']
,['1 week 4 days 13 hours 46 minutes 40 seconds', '1.000 Msec']
,['2 months 2 hours', '5.191 Msecs']
,['16 minutes 39 seconds', '999 seconds']
].forEach(t=>console.log(t[0]+' '+f(t[0])+' (Check:'+t[1]+')'))
<pre id=O></pre>


2

Python,第366个 363字节

d={};l=1;q=str.replace;i=q(raw_input(),"ie","y")
for u,t in zip('second minute hour day week month year decade century'.split(),(1,60,60,24,7,30./7,73./6,10,10)):l=t*l;d[u]=d[u+"s"]=l
while" "in i:
 i=q(q(i," ","*",1)," ","+",1)
q=eval(i,d);f={};l=1
for u in('second','Ksec','Msec','Gsec'):
 l*=1e3
 if q<l:q=q*1e3/l;print"%.3f %s%s"%(q,u,("s","")[q<1.001]);break

q=eval(i,d);f={};l=1在行中有不必要的缩进,这会破坏代码。此外,您可以使用10.73.代替10.0和来保存2个字节73.0。另外,在之后也不需要空格print
2015年

2

SpecBAS - 476个 471字节

因为没有什么比行号和GOTO语句更能说明“在我们的技术优势之前比以往更出色” :-)

1 INPUT e$: DIM t$(SPLIT e$,NOT " "): DIM m=31536e5,31536e4,31536e3,2592e3,604800,86400,3600,60,1
2 LET q=0,n$=" cedeyemowedahomise"
3 FOR i=1 TO ARSIZE t$() STEP 2: LET t=VAL t$(i),u$=t$(i+1)( TO 2),p=POS(u$,n$)/2: INC q,t*m(p): NEXT i
4 IF q>=1e9 THEN LET r=q/1e9,r$=" G": GO TO 8
5 IF q>=1e6 THEN LET r=q/1e6,r$=" M": GO TO 8
6 IF q>999 THEN LET r=q/1e3,r$=" K": GO TO 8
7 IF q<1e3 THEN LET r=q,r$=" "
8 PRINT USING$("&.*0###",r);r$;"sec"+("ond" AND q<1e3)+("s" AND r>1)

1

C#(在LinqPad中为函数),460字节

void Main(){var x=Console.ReadLine().Split(' ');long s=0,v,i=0;for(;i<x.Length;){v=long.Parse(x[i++]);var w=x[i++].Substring(0,2);s+=w=="ce"?v*3153600000:w=="de"?v*315360000:w=="ye"?v*31536000:w=="mo"?v*2592000:w=="we"?v*604800:w=="da"?v*86400:w=="ho"?v*3600:w=="mi"?v*60:v;}decimal k=1000,m=k*k,g=m*k,r=0;var o="sec";r=s/g>=1?s/g:s/m>=1?s/m:s/k>=1?s/k:s;o=s/g>=1?"G"+o:s/m>=1?"M"+o:s/k>=1?"K"+o:o+"ond";Console.WriteLine(Math.Round(r,3)+" "+o+(r==1?"":"s"));}

松散:

void Main()
{
    var x=Console.ReadLine().Split(' ');
    long s=0,v,i=0;
    for(;i<x.Length;)
    {
        v=long.Parse(x[i++]);
        var w=x[i++].Substring(0,2);
        s+=w=="ce"?v*3153600000:w=="de"?v*315360000:w=="ye"?v*31536000:w=="mo"?v*2592000:w=="we"?v*604800:w=="da"?v*86400:w=="ho"?v*3600:w=="mi"?v*60:v;
    }
    decimal k=1000,m=k*k,g=m*k,r=0;
    var o="sec";
    r=s/g>=1?s/g:s/m>=1?s/m:s/k>=1?s/k:s;
    o=s/g>=1?"G"+o:s/m>=1?"M"+o:s/k>=1?"K"+o:o+"ond";
    Console.WriteLine(Math.Round(r,3)+" "+o+(r==1?"":"s"));
}

1

Mathematica 296281字节

h:分手输入串入量幅度和单元的列表,后CapitalizePluralize将输入单元分为数学Quantity的,从中导出的总秒数。

d将秒转换为适当的单位。s如果时间对应于1个单位(任何类型),则将删除决赛。

只需对代码进行少量调整,此方法就可以将自然语言输入转换为任何常规或非常规的测量系统。

h=Tr[UnitConvert[Quantity@@{ToExpression@#,Capitalize@Pluralize@#2},"Seconds"]&@@@Partition[StringSplit@#,2]][[1]]&;
d=ToString[N@#/(c=10^{9,6,3,0})[[p=Position[l=NumberDecompose[#,c],x_/;x>0][[1,1]]]]]<>StringDrop[{" Gsecs"," Msecs"," Ksecs"," seconds"}[[p]],-Boole[Tr[l]==1]]&
z=d@h@#&;

放入表格形式:

z1[n_]:={n,z@n}

Grid[z1 /@ {"1 hour", "2 day", "2 weeks", "1 year", "32 years", 
   "1 second", "1 century 6 decades", "255 centuries", 
   "2 weeks 6 days 1 hour 7 minutes", 
   "1 week 3 days 3 hours 46 minutes 40 seconds", 
   "1 week 4 days 13 hours 46 minutes 40 seconds", "2 months 2 hours",
    "16 minutes 39 seconds"}, Alignment -> Right]

图片


0

哈斯克尔, 565 555字节

import Data.List
import Numeric
import Data.Bool
i=isPrefixOf
s x=showFFloat(Just 3)x""
r=read
f=fromIntegral
b=bool"s"""
c=b.(=="1.000")
h(c:u:l)
 |i"s"u=(r c)+h l
 |i"mi"u=(r c*60)+h l
 |i"h"u=(r c*3600)+h l
 |i"da"u=(r c*86400)+h l
 |i"w"u=(r c*604800)+h l
 |i"mo"u=(r c*2592000)+h l
 |i"y"u=(r c*31536000)+h l
 |i"de"u=(r c*315360000)+h l
 |True=(r c*3153600000)+h l
h _=0
q i
 |v<-s((f i)/10^9),i>=10^9=v++" Gsec"++c v
 |v<-s((f i)/10^6),i>=10^6=v++" Msec"++c v
 |v<-s((f i)/1000),i>=1000=v++" ksec"++c v
 |True=show i++" second"++b(i==1)
t=q.h.words

我可以肯定地说,我在这里错过了很多高尔夫机会……我想成为高尔夫初学者的代价。

我的答案是一个函数,该函数将包含地球时间的字符串作为输入参数,并返回Qeng Ho时间。

PS:我愚蠢地忘记了3位数的精度……这确实增加了字节数。

PPS:更好地选择的顶级表达式减少了10个字节…并且现在应该可以准确启动。


0

Matlab 315字节

K='cedeyemowedahomiseconds';Q=' KMGT';for j=1:9;y(j)=double(~isempty(strfind(S,K(2*j-1:2*j))));end
y(y==1)=sscanf(S,repmat('%d %*s ',1,9));y=86400*sum(datenum([sum(y(1:3)*10.^[2;1;0]),y(4),y(5:6)*[7;1],y(7:9)]));z=floor(log10(y)/3);y=num2str(y/10^(3*z)+1e-4);[y(1:4),' ',Q(z+1),K(17:23-(y(1:4)=='1.00'))]

测试:

S = '2 centuries 1 decade 2 years 3 months 3 weeks 4 days 1 hour 44 minutes 58 seconds';

输出:

ans =
6.69 Gseconds
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.