หน่วยเวลา Qeng Ho


40

ในหนังสือที่ยอดเยี่ยมและน่าหลงใหลของDeepor in the Skyของ Vernor Vinge (ซึ่งฉันขอแนะนำอย่างยิ่ง1 ), Qeng Hoซึ่งเป็นวัฒนธรรมที่ครอบคลุมระบบดาวต่าง ๆ ไม่มีแนวคิดเรื่อง "วัน" "เดือน" ปี "ฯลฯ และด้วยเหตุนี้จึงมีระบบบอกเวลาที่เป็นเอกลักษณ์ที่วัดเวลาทั้งหมดในไม่กี่วินาที หน่วยที่ใช้บ่อยที่สุดคือKsec (kilosecond), Msec (megasecond) และGsec (gigasecond) นี่คือแผนภูมิที่มีประโยชน์จากสำเนาหนังสือของฉันเอง (เนื่องจากฉันไม่สามารถหาได้ออนไลน์):

แผนภูมิที่มีประโยชน์

คุณกำลังบินอยู่บนPham Nuwenและคุณเพิ่งได้รับข้อความจากดาวเคราะห์แปลกประหลาดที่ไม่รู้จักที่เรียกว่า " โลก " 2พวกเขาใช้หน่วยเวลาที่แตกต่างจากที่คุณทำและคอมพิวเตอร์ของคุณไม่รู้จักหน่วยเวลา ในฐานะโปรแกรมเมอร์ประจำถิ่นของเรืองานของคุณคือแก้ไขรหัสการจัดการเวลาเพื่อให้สามารถจดจำหน่วยเวลาของโลกได้

โดยธรรมชาติเนื่องจากคุณเพิ่งจะเป็นหวัดสำหรับ Ksecs อีกสองสามตัวคุณต้องการทำให้โค้ดของคุณสั้นที่สุดเท่าที่จะเป็นไปได้เพื่อให้สามารถเขียนได้อย่างรวดเร็ว โชคดีในฐานะที่เป็นวัฒนธรรมการค้าระหว่างดวงดาว Qeng Ho สามารถเข้าถึงภาษาการเขียนโปรแกรมทุกภาษาที่คิดค้นขึ้น

อินพุต

การป้อนข้อมูลจะเป็นสายเดียวที่มีหนึ่งหรือมากกว่าหนึ่งพื้นที่แยก ส่วนประกอบ องค์ประกอบที่ถูกกำหนดให้เป็นเลขจำนวนเต็ม> 0 และ≤ 255 แล้วพื้นที่และจากนั้นหนึ่งsecond, minute, hour, day, week, month, year, decadeหรือ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 ที่ใหญ่ที่สุดที่สั้นลงหรือใช้เวลาเท่ากันกับอินพุต - โดยพื้นฐานแล้วค้นหาหน่วยที่ใหญ่ที่สุดที่มีอย่างน้อยหนึ่งหน่วย

  • แปลงจำนวนเวลาทั้งหมดที่กำหนดในอินพุตเป็นหน่วยนี้และส่งออกผลลัพธ์ปัดเศษเป็นทศนิยมสามตำแหน่ง

คุณอาจเลือกวิธีการใช้วิธีใดวิธีหนึ่งต่อไปนี้: การปัดเศษขึ้นปัดเศษลงปัดเศษจากศูนย์หรือปัดเศษไปยัง∞หรือ-∞ หากผลลัพธ์ที่ปัดเศษสิ้นสุดลง0คุณสามารถลบศูนย์ต่อท้ายหรือเก็บไว้ได้มากเท่าที่คุณต้องการ

หากผลกลมเป็นสิ่ง1.000ที่คุณต้องใช้รูปเอกพจน์ ( second, Ksec, Msec, Gsec); มิฉะนั้นจะใช้รูปพหูพจน์ ( seconds, Ksecs, Msecs, Gsecs)

ในบางกรณีคุณอาจกำลังใช้หน่วยของตัวอย่างเช่น Ksec แต่ได้ผลลัพธ์ที่ปัดเศษเป็น 1,000,000 Ksecs ในกรณีนี้คุณอาจเพียงแค่การส่งออก แทน1000.000 Ksecs1 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: เฉพาะในกรณีที่คุณชอบ scifi ยากแน่นอน ในกรณีนี้ฉันขอแนะนำให้อ่านA Fire Upon the Deepก่อนซึ่งเป็นสิ่งที่ฉันคิดว่ายอดเยี่ยมมาก

2: ดีเทคนิค "Old Earth" ถูกกล่าวถึงหลายครั้งในA Deepness in the Skyแต่ ...


กรณีทดสอบ 9 ดูเหมือนไม่ถูกต้อง (ดูคำตอบของฉัน)
edc65

1
เรือลำนี้ไม่รู้จักโลกเวลา แต่มีความเข้าใจเต็มรูปแบบของภาษาการเขียนโปรแกรม Earth ทั้งหมด ตรรกะมาก </sarcasm>
ตบมือ

2
แดงฉันมีวิธีแก้ปัญหาทางคณิตศาสตร์สั้น ๆ โดยใช้การสนับสนุนหน่วยในตัว แต่แปล2 months 2 hoursว่า "2 เดือน * 2 ชั่วโมง"
2012rcampion

1
อืมฉันสังเกตว่าปัจจัยเหล่านี้ดูแปลกไปกว่าฟังก์ชั่นการจัดการเวลาที่ล้าสมัยซึ่งไม่มีใครใช้ในภาษาเหล่านี้มากมาย
Random832

คำตอบ:


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 ในแต่ละถัดไป→1E3 z
อดัม

ใช่ถูกต้องอย่างแน่นอน และเนื่องจากว่ามีเพียง 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บรรทัดซึ่งแบ่งรหัส นอกจากนี้คุณสามารถบันทึก 2 ไบต์โดยใช้10.และ73.แทนและ10.0 73.0นอกจากนี้ยังไม่จำเป็นต้องมีพื้นที่ว่างหลังจากprintนั้น
Aland

2

SpecBAS - 476 471 ไบต์

เพราะไม่มีอะไรพูดว่า "cower ก่อนความเป็นเลิศทางเทคโนโลยีของเรา" ดีกว่าหมายเลขบรรทัดและคำสั่ง 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"));}

ungolfed:

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 296 281 ไบต์

h: หลังจากเลิกสายป้อนเข้าไปในรายการเคาะปริมาณและหน่วย, CapitalizeและPluralizeแปลงหน่วยการป้อนข้อมูลลงในมาติกาQuantity's จากการที่จำนวนวินาทีที่ได้รับมา

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]

pic


0

Haskell, 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.