Unidades de tempo Qeng Ho


40

No excelente e fascinante livro de Vernor Vinge, A Deepness in the Sky (que, a propósito, eu recomendo muito 1 ), o Qeng Ho , uma cultura que abrange vários sistemas estelares, não tem noção de "dias", "meses" ". anos ", etc., e, portanto, possui um sistema exclusivo de cronometragem que mede o tempo inteiramente em segundos. As unidades mais usadas são o Ksec (kilosegundo), Msec (megasegundo) e Gsec (gigasegundo). Aqui está um gráfico útil da minha própria cópia do livro (já que não consigo encontrá-lo online):

gráfico acessível

Você está voando no Pham Nuwen e acabou de receber uma mensagem de um planeta estranho e desconhecido chamado " Terra ". 2 Eles usam unidades de tempo diferentes das que você usa e seus computadores não os reconhecem. Como programador-arqueólogo residente da nave, seu trabalho é corrigir o código de manipulação do tempo para que ele reconheça as unidades de tempo da Terra .

Naturalmente, como você não consegue dormir por mais alguns Ksecs, você deseja tornar seu código o mais curto possível para que ele possa ser escrito rapidamente. Felizmente, como uma cultura comercial interestelar, o Qeng Ho tem acesso a todas as linguagens de programação inventadas.

Entrada

A entrada será uma única sequência contendo um ou mais componentes separados por espaço . Um componente é definido como um número inteiro> 0 e ≤ 255, em seguida, um espaço, e, em seguida, uma de second, minute, hour, day, week, month, year, decade, ou century, possivelmente, no plural (com um adicional s, ou centuriespara o último caso).

Aqui estão algumas entradas de exemplo válidas:

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

Você pode assumir o seguinte sobre a entrada:

  • A pluralização de unidades sempre estará de acordo com o número relevante.

  • Se houver vários componentes na entrada, eles sempre estarão em ordem decrescente de comprimento.

Aqui está o que as várias unidades de entrada significam, para os propósitos deste desafio:

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

Saída

Aqui estão as unidades Qeng Ho que seu código precisa oferecer suporte:

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

Use o seguinte algoritmo para determinar a saída do seu código:

  • Primeiro, adicione a quantidade total de tempo que a entrada representa.

  • Encontre a maior unidade Qeng Ho que seja mais curta ou a mesma quantidade de tempo que a entrada - essencialmente, encontre a maior unidade da qual exista pelo menos uma delas.

  • Converta a quantidade total de tempo fornecida na entrada nesta unidade e produza o resultado, arredondado para três casas decimais.

Você pode escolher qual dos seguintes métodos usar: arredondar para cima, arredondar para baixo, arredondar para longe de zero ou arredondar para ∞ ou -∞. Se o resultado arredondado terminar 0, você poderá remover os zeros à direita ou manter quantos quiser (ou fazer os dois, dependendo da entrada).

Se o resultado arredondado é exatamente 1.000, você deve usar a forma singular ( second, Ksec, Msec, Gsec); de outro modo, utilizar a forma plural ( seconds, Ksecs, Msecs, Gsecs).

Em certos casos extremos, você pode estar usando a unidade de, por exemplo, Ksec, mas obtém um resultado arredondado de 1000.000 Ksecs. Nesse caso, você pode simplesmente emitir em 1000.000 Ksecsvez de 1 Msec.

Você sempre pode assumir que a entrada está em ordem decrescente de unidades (século, década, ano etc.); além disso, o componente que vem depois de qualquer unidade sempre será mais curto (ou seja, 1 decade 20 yearsé uma entrada inválida).

Casos de teste

Nota: os resultados marcados com um asterisco ( *) podem variar em uma quantidade desprezível devido a diferenças de arredondamento.

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

Regras

  • Isso é , então o código mais curto em bytes vence.

1: somente se você gosta de ficção científica, é claro. Nesse caso, recomendo ler A Fire Upon the Deep primeiro, o que é (na minha opinião) ainda mais fantástico.

2: bem, tecnicamente, "Old Earth" é mencionada várias vezes em A Deepness in the Sky , mas ...


Caso de teste 9 parece incorreta (ver minha resposta)
edc65

11
Esta nave não conhece o tempo da Terra, mas tem um entendimento completo de todas as linguagens de programação da Terra. Muito lógico </sarcasm>
bata em

2
Porra, eu tinha uma solução Mathematica muito curta, usando o suporte da unidade embutida, mas ela interpreta 2 months 2 hourscomo "2 meses * 2 horas".
2012rcampion

11
Hmm, percebo que esses fatores se parecem estranhamente com os das funções obsoletas de manipulação de tempo que ninguém usa em muitas dessas linguagens.
Random832

Respostas:


6

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

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

Obrigado ao ngn por eliminar 13 bytes.

Deve ter ⎕IO←0, que é padrão em muitos APLs.

Experimente online!


Se você atribuir 1E3 a um nome (como z), na primeira instância você desperdiçou dois caracteres, na segunda instância você já salvou um e, a partir da terceira instância, você estará salvando dois caracteres. Não é?
Lstfano

@lstefano Não, o primeiro custará 4: ⌊1E3⍟⌊(z←1E3)⍟e depois salvará 2 em cada um dos próximos 1E3z.
Adám 28/06

Sim, absolutamente certo. E dado que existem apenas 3 deles, não há ganho. Desculpe pelo barulho.
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 bytes

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

Você tem um recuo desnecessário na q=eval(i,d);f={};l=1linha, que quebra o código. Além disso, você pode salvar 2 bytes usando 10.e em 73.vez de 10.0e 73.0. Além disso, não há necessidade de espaço depois print.
Aland #

2

SpecBAS - 476 471 bytes

Porque nada diz "encolher-se diante de nossa superioridade tecnológica" melhor do que números de linha e declarações 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 # (no LinqPad como função), 460 bytes

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 bytes

h: Depois de dividir a sequência de entrada em uma lista de grandezas e unidades de quantidade Capitalizee Pluralizeconverter as unidades de entrada em Mathematica Quantity's, a partir da qual o número total de segundos é derivado.

dconverte segundos nas unidades apropriadas. A final sé removida se o tempo corresponder a 1 unidade (de qualquer tipo).

Com pequenos ajustes no código, essa abordagem deve funcionar para a conversão da entrada da linguagem natural em qualquer sistema de medição, convencional ou não.

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

Coloque em forma de tabela:

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]

foto


0

Haskell, 565 555 bytes

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

Tenho certeza de que estou perdendo tantas oportunidades de golfe aqui ... Acho que o preço de ser um iniciante no golfe.

Minha resposta é uma função que pega uma string contendo o tempo da Terra como parâmetro de entrada e retorna o tempo Qeng Ho.

PS: Eu estupidamente esqueci a precisão de 3 dígitos ... o que faz a contagem de bytes aumentar.

PPS: Expressões de nível superior mais bem escolhidas eliminadas 10 bytes ... e agora deve ser preciso inicializar.


0

Matlab 315 bytes

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

Teste:

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

Saída:

ans =
6.69 Gseconds
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.