Qeng Ho unità di tempo


40

Nell'eccellente e affascinante libro di Vernor Vinge A Deepness in the Sky (che, a proposito, consiglio vivamente 1 ), il Qeng Ho , una cultura che abbraccia vari sistemi stellari, non ha idea di "giorni", "mesi" " anni ", ecc., e quindi ha un sistema di cronometraggio unico che misura il tempo interamente in secondi. Le unità più comunemente usate sono Ksec (chilosecondi), Msec (megasecondi) e Gsec (gigasecondi). Ecco un utile diagramma dalla mia copia del libro (poiché non riesco a trovarlo online):

grafico a portata di mano

Attualmente stai volando sul Pham Nuwen e hai appena ricevuto un messaggio da uno strano pianeta sconosciuto chiamato " Terra ". 2 Usano unità di tempo diverse da te e i tuoi computer non riconoscono le loro. In qualità di programmatore-archeologo residente della nave, il tuo compito è correggere il codice di gestione del tempo in modo che riconosca le unità di tempo terrestri .

Naturalmente, dato che hai dormito solo per qualche altro Ksec, vuoi rendere il tuo codice il più breve possibile in modo che possa essere scritto rapidamente. Fortunatamente, come cultura commerciale interstellare, il Qeng Ho ha accesso a tutti i linguaggi di programmazione inventati.

Ingresso

L'input sarà una singola stringa contenente uno o più componenti separati da spazio . Un componente è definito come un numero intero> 0 e ≤ 255, poi uno spazio, e quindi una delle second, minute, hour, day, week, month, year,decade , o century, eventualmente plurale (con aggiunta so centuriesper l'ultimo caso).

Ecco alcuni input di esempio validi:

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

Si può presumere quanto segue sull'input:

  • La pluralizzazione delle unità concorderà sempre con il numero pertinente.

  • Se ci sono più componenti nell'input, saranno sempre in ordine decrescente di lunghezza.

Ecco cosa significano le varie unità di input, ai fini di questa sfida:

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

Produzione

Ecco le unità Qeng Ho che il tuo codice deve supportare:

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

Utilizzare il seguente algoritmo per determinare l'output del codice:

  • Innanzitutto, sommare il tempo totale rappresentato dall'input.

  • Trova l'unità Qeng Ho più grande che è più breve o la stessa quantità di tempo dell'input; in sostanza, trova l'unità più grande di cui esiste almeno una.

  • Converti la quantità totale di tempo indicata nell'input in questa unità e genera il risultato, arrotondato al terzo decimale.

È possibile scegliere quale dei seguenti metodi utilizzare: arrotondamento per eccesso, arrotondamento per difetto, arrotondamento per difetto da zero o arrotondamento per ∞ o -∞. Se il risultato arrotondato termina 0, puoi rimuovere gli zero finali o mantenerne quanti ne vuoi (o fare entrambi, a seconda dell'input).

Se il risultato arrotondato è esattamente 1.000, è necessario utilizzare la forma singolare ( second, Ksec, Msec, Gsec); altrimenti, utilizzare il plurale ( seconds, Ksecs, Msecs,Gsecs ).

In alcuni casi limite, potresti usare l'unità di, ad esempio, Ksec, ma ottenere un risultato arrotondato di 1000.000 Ksec. In questo caso, puoi semplicemente produrre 1000.000 Ksecsinvece di 1 Msec.

Puoi sempre presumere che l'input sia in ordine decrescente di unità (secolo, decennio, anno, ecc.); inoltre, il componente che viene dopo una data unità sarà sempre più corto (ovvero1 decade 20 years input non valido).

Casi test

Nota: i risultati contrassegnati con un asterisco ( *) possono variare di un importo trascurabile a causa delle differenze di arrotondamento.

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

Regole

  • Questo è , quindi vince il codice più breve in byte.

1: solo se ti piace hard scifi, ovviamente. Nel qual caso consiglio di leggere prima A Fire Upon the Deep , che è (secondo me) ancora più fantastico.

2: beh, tecnicamente la "Vecchia Terra" è menzionata più volte in Una profondità nel cielo , ma ...


Il caso di test 9 sembra errato (vedi la mia risposta)
edc65,

1
Questa nave non conosce il tempo terrestre, ma ha una piena comprensione di tutti i linguaggi di programmazione terrestre. Molto logico. </sarcasm>
applaude il

2
Dang, avevo una soluzione Mathematica davvero breve che utilizzava il supporto unità integrato, ma interpretava 2 months 2 hourscome "2 mesi * 2 ore".
2012rcampion

1
Hmm, noto che questi fattori sembrano stranamente simili a quelli delle funzioni obsolete di gestione del tempo che nessuno usa in molte di queste lingue.
Casuale 832

Risposte:


6

APL (Dyalog APL) , 157 156 154 151 154 141 142 byte

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

Grazie a ngn per la rasatura di 13 byte.

Deve avere ⎕IO←0, che è predefinito in molti APL.

Provalo online!


Se assegni 1E3 a un nome (come z), nella prima istanza hai perso due caratteri, nella seconda istanza ne hai già salvato uno e dalla terza istanza in poi stai salvando due caratteri. No?
lstefano,

@lstefano No, il primo avrà un costo di 4: ⌊1E3⍟⌊(z←1E3)⍟e quindi ne salverà 2 su ciascuno dei successivi 1E3z.
Adám,

Sì, assolutamente. E dato che ce ne sono solo 3, nessun guadagno. Scusa per il rumore.
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 byte

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

Hai un rientro non necessario in q=eval(i,d);f={};l=1linea, che interrompe il codice. Inoltre, puoi salvare 2 byte usando 10.e 73.invece di 10.0e 73.0. Inoltre, non è necessario spazio dopo print.
al

2

SpecBAS - 476 471 byte

Perché nulla dice "cower prima della nostra superiorità tecnologica" meglio dei numeri di riga e delle dichiarazioni 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 # (in LinqPad come funzione), 460 byte

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 byte

h: Dopo aver suddiviso la stringa di input in un elenco di magnitudini e unità di quantità Capitalizee Pluralizeconvertite le unità di input in MathematicaQuantity , da cui deriva il numero totale di secondi.

dconverte i secondi nelle unità appropriate. Il finales viene rimosso se il tempo corrisponde a 1 unità (di qualsiasi tipo).

Con piccole modifiche al codice, questo approccio dovrebbe funzionare per la conversione dell'input del linguaggio naturale in qualsiasi sistema di misurazione, convenzionale o no.

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

Metti in forma di tabella:

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 byte

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

Sono ragionevolmente sicuro che mi sto perdendo così tante opportunità di golf qui ... Il prezzo di essere un principiante del golf credo.

La mia risposta è una funzione che prende una stringa contenente il tempo terrestre come parametro di input e restituisce il tempo Qeng Ho.

PS: mi sono stupidamente dimenticato della precisione a 3 cifre ... che fa aumentare il conteggio dei byte.

PPS: espressioni di livello superiore scelte in modo migliore, eliminate di 10 byte ... e ora dovrebbe essere preciso per l'avvio.


0

Matlab 315 byte

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';

Produzione:

ans =
6.69 Gseconds
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.