Одиниці часу Qeng Ho


40

У чудовій і захоплюючій книзі Вернора Вінге « Глибокість у небі» (яку, до речі, настійно рекомендую 1 ), Кенг Хо , культура, яка охоплює різні зіркові системи, не має поняття «дні», «місяці», « років "і т. д., а отже, існує унікальна система хронометражу, яка цілком вимірює час у секундах. Найчастіше використовуються одиниці - Ksec (кілосекунда), Msec (мегасекунда) та Gsec (гігасекунда). Ось зручна діаграма з моєї власної копії книги (оскільки я не можу знайти її в Інтернеті):

зручна діаграма

Ви зараз летите на Фам Нувен , і ви щойно отримали повідомлення від чужої, невідомої планети під назвою " Земля ". 2 Вони використовують різні часові одиниці, ніж ви, і ваші комп'ютери не розпізнають їх. Як програміст-археолог-резидент корабля, ваше завдання полягає в виправлення коду обробки часу, щоб він розпізнавав одиниці часу Землі .

Природно, оскільки вам не вистачає холоду ще протягом декількох Ksec, ви хочете зробити свій код якомога коротшим, щоб його можна було швидко записати. На щастя, як міжзоряна культура торгівлі, 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, яка коротша або стільки ж часу, що і вхід, по суті, знайдіть найбільшу одиницю, з якої є хоча б одна.

  • Перетворіть загальну кількість часу, введеного на вході, в цей блок, і виведіть результат, округлений до трьох знаків після коми.

Ви можете обрати один із наступних методів: округлення, округлення вниз, округлення від нуля або округлення до towards або -∞. Якщо округлий результат закінчується 0, ви можете або видалити кінцеві нулі, або зберегти стільки, скільки вам потрібно (або зробити обидва, залежно від введення).

Якщо округлений результат точно 1.000, ви повинні використовувати особливу форму ( second, Ksec, Msec, Gsec); в іншому випадку використовувати форму множини ( seconds, Ksecs, Msecs, Gsecs).

У певних крайніх випадках ви можете використовувати одиницю, наприклад, Ksec, але отримаєте округлий результат у 1000 000 Ksec. У цьому випадку ви можете просто вивести 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, звичайно. У такому випадку я рекомендую прочитати спочатку A Fire Upon the Deep , що (на мій погляд) ще більш фантастичне.

2: ну, технічно "Стара Земля" згадується кілька разів у "Глибині в небі" , але ...


Тестовий випадок 9 здається невірним (див. Мою відповідь)
edc65

1
Цей корабель не знає часу Землі, але має повне розуміння всіх мов програмування Землі. Дуже логічно. </sarcasm>
плескайте

2
Данг, у мене було дуже коротке рішення Mathematica за допомогою вбудованої підтримки, але це трактується 2 months 2 hoursяк "2 місяці * 2 години".
2012рcampion

1
Хм, я зауважую, що ці фактори виглядають дивним чином, як і ті у застарілих функціях обробки часу, які ніхто не використовує у багатьох цих мовах.
Випадково832

Відповіді:


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 на кожному наступному 1E3z.
Адам

Так, абсолютно прав. А враховуючи, що їх всього 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.
аланд

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

неозорений:

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

рис


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.