Jednostki czasu Qeng Ho


40

W doskonałej i fascynującej książce Vernor Vinge A Deepness in the Sky (którą, nawiasem mówiąc, gorąco polecam 1 ), Qeng Ho , kultura obejmująca różne układy gwiezdne, nie ma pojęcia „dni”, „miesiące”, „ lata ”itd., a zatem ma unikalny system pomiaru czasu, który mierzy czas całkowicie w sekundach. Najbardziej powszechnie stosuje się jednostki są Ksec (kilosecond) Msec (megasecond) i Gsec (gigasecond). Oto przydatny wykres z mojej własnej kopii książki (ponieważ nie mogę go znaleźć w Internecie):

poręczny wykres

Lecisz obecnie na Pham Nuwen i właśnie otrzymałeś wiadomość z dziwnej, nieznanej planety o nazwie „ Ziemia ”. 2 Używają innych jednostek czasu niż ty, a twoje komputery ich nie rozpoznają. Jako rezydent-programista-archeolog statku, twoim zadaniem jest załatanie kodu czasu, tak aby rozpoznawał ziemskie jednostki czasu.

Oczywiście, ponieważ nie możesz zasnąć tylko przez kilka kolejnych Kseków, chcesz, aby Twój kod był jak najkrótszy, aby można go było szybko napisać. Na szczęście, jako międzygwiezdna kultura handlowa, Qeng Ho ma dostęp do każdego wynalezionego języka programowania.

Wejście

Dane wejściowe będą pojedynczym ciągiem zawierającym jeden lub więcej komponentów oddzielonych spacją . Składnik jest zdefiniowany jako liczba całkowita> 0 i ≤ 255, a następnie miejsca, i następnie jeden z second, minute, hour, day, week, month, year, decade, i century, ewentualnie mnogiej (z dodatkowym s, a centuriesw ostatnim przypadku).

Oto kilka przykładowych danych wejściowych:

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

Możesz przyjąć następujące dane wejściowe:

  • Pluralizacja jednostek zawsze będzie zgodna z odpowiednią liczbą.

  • Jeśli na wejściu znajduje się wiele komponentów , zawsze będą one w malejącej kolejności długości.

Oto, co oznaczają różne jednostki wejściowe na potrzeby tego wyzwania:

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

Wydajność

Oto jednostki Qeng Ho, które Twój kod musi obsługiwać:

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

Użyj następującego algorytmu, aby określić wyjście kodu:

  • Najpierw zsumuj całkowity czas reprezentowany przez dane wejściowe.

  • Znajdź największą jednostkę Qeng Ho, która jest krótsza lub ma tyle samo czasu co dane wejściowe - w zasadzie znajdź największą jednostkę, z której jest co najmniej jedna.

  • Przelicz całkowity czas podany na wejściu na tę jednostkę i wyślij wynik zaokrąglony do trzech miejsc po przecinku.

Możesz wybrać jedną z następujących metod: zaokrąglanie w górę, zaokrąglanie w dół, zaokrąglanie od zera lub zaokrąglanie w kierunku ∞ lub -∞. Jeśli zaokrąglony wynik kończy się na 0, możesz albo usunąć końcowe zera, albo zachować tyle, ile chcesz (lub zrobić jedno i drugie, zależnie od danych wejściowych).

Jeśli wynik jest dokładnie zaokrąglone 1.000, należy użyć formy liczby pojedynczej ( second, Ksec, Msec, Gsec); w przeciwnym razie, należy liczbę mnogą ( seconds, Ksecs, Msecs, Gsecs).

W niektórych przypadkach może być używana jednostka, na przykład Ksec, ale uzyskany zaokrąglony wynik to 1000 000 Kseków. W takim przypadku możesz po prostu wydrukować 1000.000 Ksecszamiast 1 Msec.

Zawsze możesz założyć, że dane wejściowe są w malejącej kolejności jednostek (wiek, dekada, rok itp.); ponadto element występujący po dowolnej jednostce będzie zawsze krótszy (to znaczy, że 1 decade 20 yearsbędzie nieprawidłowy).

Przypadki testowe

Uwaga: wyniki oznaczone gwiazdką ( *) mogą różnić się nieznacznie ze względu na różnice w zaokrąglaniu.

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

Zasady

  • To jest , więc wygrywa najkrótszy kod w bajtach.

1: oczywiście tylko jeśli lubisz twarde scifi. W takim przypadku polecam najpierw przeczytać A Fire Upon the Deep , który jest (moim zdaniem) jeszcze bardziej fantastyczny.

2: technicznie rzecz biorąc, „Stara Ziemia” jest kilkakrotnie wspominana w A Deepness in the Sky , ale ...


Przypadek testowy 9 wydaje się niepoprawny (patrz moja odpowiedź)
edc65

1
Ten statek nie zna czasu na Ziemi, ale w pełni rozumie wszystkie języki programowania na Ziemi. Bardzo logiczne. </sarcasm>
klaszcz

2
Dang, miałem naprawdę krótkie rozwiązanie Mathematica z wykorzystaniem wbudowanej obsługi jednostek, ale interpretuje to 2 months 2 hoursjako „2 miesiące * 2 godziny”.
2012rcampion

1
Hmm, zauważam, że te czynniki wyglądają dziwnie jak te w przestarzałych funkcjach zarządzania czasem, których nikt nie używa w wielu z tych języków.
Random832,

Odpowiedzi:


6

APL (Dyalog APL) , 157 156 154 151 154 141 142 142 bajtów

{∊(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}

Dzięki ngn za golenie 13 bajtów.

Musi mieć ⎕IO←0, co jest domyślne w wielu aplikacjach APL.

Wypróbuj online!


Jeśli przypiszesz 1E3 do nazwy (np. Z), w pierwszym przypadku zmarnowałeś dwa znaki, w drugim przypadku już zapisałeś jeden, a od trzeciego wystąpienia zapisujesz dwa znaki. Nie ty
lstefano

@lstefano Nie, pierwszy będzie kosztował 4: ⌊1E3⍟→, ⌊(z←1E3)⍟a następnie zapisze 2 na każdym następnym 1E3z.
Adám

Tak, absolutnie słuszne. A biorąc pod uwagę, że są tylko 3, nie ma zysku. Przepraszam za hałas.
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 bajtów

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

Masz niepotrzebne wcięcia w q=eval(i,d);f={};l=1linii, które psują kod. Poza tym możesz zapisać 2 bajty za pomocą 10.i 73.zamiast 10.0i 73.0. Ponadto nie ma już potrzeby zajmowania miejsca print.
i

2

SpecBAS - 476 471 bajtów

Ponieważ nic nie mówi „kulić się przed naszą przewagą technologiczną” lepiej niż numery linii i oświadczenia 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 # (w LinqPad jako funkcja), 460 bajtów

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

bez golfa:

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 bajtów

h: Po rozbiciu ciągu wejściowego na listę wielkości wielkości i jednostek Capitalizeoraz Pluralizeprzekonwertowanie jednostek wejściowych na Mathematica Quantity, na podstawie których obliczana jest całkowita liczba sekund.

dkonwertuje sekundy na odpowiednie jednostki. Finał sjest usuwany, jeśli czas odpowiada 1 jednostce (dowolnego rodzaju).

Po drobnych zmianach w kodzie podejście to powinno działać w celu konwersji danych w języku naturalnym na dowolny system pomiarowy, konwencjonalny lub nie.

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@#&;

Umieść w formie tabeli:

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]

fotka


0

Haskell, 565 555 bajtów

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

Jestem dość pewny, że tracę tu tak wiele okazji do gry w golfa ... Chyba cena początkującego golfa.

Moja odpowiedź to funkcja przyjmująca ciąg znaków zawierający czas ziemski jako parametr wejściowy i zwracająca czas Qeng Ho.

PS: Głupio zapomniałem o 3 cyfrowej precyzji… która zwiększa liczbę bajtów.

PPS: Lepiej wybrane wyrażenia najwyższego poziomu straciły 10 bajtów… i powinno być teraz dokładne uruchamianie.


0

Matlab 315 bajtów

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

Test:

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

Wynik:

ans =
6.69 Gseconds
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.