Кенг Хо единицы времени


40

В прекрасной и увлекательной книге Вернора Винджа « Глубина в небе» (которую я, кстати, очень рекомендую 1 ), культура Кенг Хо , охватывающая различные звездные системы, не имеет понятия «дни», «месяцы». лет »и т. д., и, следовательно, имеет уникальную систему учета времени, которая измеряет время полностью в секундах. Наиболее часто используемые единицы являются Ksec (kilosecond), мксек (megasecond) и GSEC (gigasecond). Вот удобная таблица из моей собственной копии книги (поскольку я не могу найти ее в Интернете):

удобный график

В настоящее время вы летите на Pham Nuwen , и вы только что получили сообщение от странной, неизвестной планеты под названием " Земля ". 2 Они используют другие единицы времени, чем вы, и ваши компьютеры их не распознают. Как постоянный программист-археолог корабля, ваша задача состоит в том, чтобы исправить код обработки времени, чтобы он распознавал земные единицы времени.

Естественно, так как вы не в состоянии простуды еще для нескольких Ksecs, вы хотите сделать свой код максимально коротким, чтобы его можно было быстро написать. К счастью, как межзвездная торговая культура, у Кенг Хо есть доступ ко всем изобретенным языкам программирования.

вход

На входе будет одна строка, содержащая один или несколько разделенных пробелами компонентов . Компонент определяется как целое число> 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, но получить округленный результат 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: только если вы любите жесткий scifi, конечно. В этом случае я рекомендую сначала прочитать «Огонь на глубине» , что (на мой взгляд) еще более фантастично.

2: хорошо, технически «Старая Земля» упоминается несколько раз в «Глубине в небе» , но ...


Тестовый пример 9 кажется неправильным (см. Мой ответ)
edc65

1
Этот корабль не знает времени Земли, но имеет полное понимание всех языков программирования Земли. Очень логично </ sarcasm>
хлоп

2
Черт, у меня было очень короткое решение Mathematica, использующее встроенную поддержку модулей, но оно интерпретируется 2 months 2 hoursкак «2 месяца * 2 часа».
2012 rcampion

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 Нет, первое будет стоить 4: ⌊1E3⍟→, ⌊(z←1E3)⍟а затем сохранить 2 на каждом следующем 1E3z.
Адам

Да, абсолютно верно. А учитывая, что их всего 3, выигрыша нет. Извините за шум.
Истефано

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.
Аланд

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

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преобразование входных единиц в значения Mathematica 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

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.