Скільки років приблизно?


29

Напишіть коротку програму, яка займає позитивну кількість секунд, що відображає вік, і виводить оцінку цього часу англійською мовою.

Ваша програма повинна виводити найменш точний пройдений час серед наступних показників та їх тривалості в секундах:

second = 1
minute = 60
hour   = 60 * 60
day    = 60 * 60 * 24
week   = 60 * 60 * 24 * 7
month  = 60 * 60 * 24 * 31
year   = 60 * 60 * 24 * 365

Приклади

input      : output
1          : 1 second
59         : 59 seconds
60         : 1 minute
119        : 1 minute
120        : 2 minutes
43200      : 12 hours
86401      : 1 day
1815603    : 3 weeks
1426636800 : 45 years

Як ви бачите вище, після часу сказання, 1 день (60 * 60 * 24 = 86400 секунд), ми більше не виводимо хвилини (години) або години (години) , а лише дні, поки ми не перевершимо час одного тижня , і так далі.

Розглянемо дану тривалість часу як вік. Наприклад, через 119 секунд минула 1 хвилина , а не 2.

Правила

  • Немає специфікацій для 0 або негативних входів.
  • Дотримуйтесь правильної плюралізації. Кожен захід, що перевищує 1, повинен містити sтаке слово.
  • Ви не можете використовувати попередньо існуючу бібліотеку, яка обслуговує функцію всієї програми.
  • Це кодовий гольф, найкоротша програма виграє Інтернет-очки.
  • Веселіться!

3
Я не розумію, як ми вибираємо одиницю чи суму. Ми круглі?
xnor

1
@xnor ми на ціле число ділимо і використовуємо найменше ненульове значення разом із його одиницею (можливо, множиною). Звідси 59 -> "59 секунд" і 86401 -> "1 день".
Джонатан Аллан

5
Ласкаво просимо до PPCG! Гарний перший виклик. Для подальшого ознайомлення є пісочниця, яка корисна для отримання зворотного зв’язку перед публікацією на основну.
Джонатан Аллан


1
Як слід округлювати числа? Якщо 119 секунд має бути 1 хвилина чи 2 хвилини? Що з 90?
користувач202729

Відповіді:


8

Желе , 62 байти

TṀị
“¢<<ð¢‘×\×€0¦7,31,365F⁸:µç“ɲþḣ⁹ḢṡṾDU¤µQƝṁ⁼ẹ»Ḳ¤ṭÇK;⁸Ç>1¤¡”s

Повна програма, що друкує результат.
(Як монадичне посилання повертає список цілого числа, за яким слідують символи)

Спробуйте в Інтернеті!

Як?

TṀị - Link 1: list of integers, K; list, V  e.g. [86401,1440,24,1,0,0,0], ["second","minute","hour","day","week","month","year"]
T   - truthy indexes of K                        [1,2,3,4]
 Ṁ  - maximum                                    4
  ị - index into V                               "day"

“¢<<ð¢‘×\×€0¦7,31,365F⁸:µç“...»Ḳ¤ṭÇK;⁸Ç>1¤¡”s - Main link: integer, N  e.g. 3599
“¢<<𢑠                                      - list of code-page indices = [1,60,60,24,1]
        \                                     - cumulative reduce with:
       ×                                      -  multiplication = [1,60,3600,86400,86400]
             7,31,365                         - list of integers = [7,31,365]
            ¦                                 - sparse application...
           0                                  - ...to index: 0 (rightmost)
         ×€                                   - ...of: multiplication for €ach = [1,60,3600,86400,[604800,2678400,31536000]]
                     F                        - flatten = [1,60,3600,86400,604800,2678400,31536000]
                      ⁸                       - chain's left argument, N    3599
                       :                      - integer divide         [3599,59,0,0,0,0,0]
                        µ                     - start a new monadic chain, call that X
                                ¤             - nilad followed by links as a nilad:
                          “...»               -   compression of "second minute hour day week month year"
                               Ḳ              -   split at spaces = ["second","minute","hour","day","week","month","year"]
                         ç                    - call the last link (1) as a dyad - i.e. f(X,["second","minute","hour","day","week","month","year"])
                                              -                             "minute"
                                  Ç           - call the last link (1) as a monad - i.e. f(X,X)
                                              -                             59
                                 ṭ            - tack                        [59,['m','i','n','u','t','e']]
                                   K          - join with spaces            [59,' ','m','i','n','u','t','e']
                                           ”s - literal character '
                                          ¡   - repeat...
                                         ¤    - ...number of times: nilad followed by link(s) as a nilad:
                                     ⁸        -   chain's left argument, X  [3599,59,0,0,0,0,0]
                                      Ç       -   call the last link (1) as a monad - i.e. f(X,X)
                                              -                             59
                                       >1     -   greater than 1?           1
                                    ;         - concatenate                 [59,' ','m','i','n','u','t','e','s']
                                              - implicit print - smashes to print  "59 minutes"

8

C, 194 180 144 144 128 символів

Дякуємо @gastropher за зменшення коду. Я забув, що C дозволяє неявні параметри, використовуючи функції стилю K & R! Також дякуємо @gmatht за ідею помістити літерали всередину замість масивів. Я поширив це на персонажів, зловживаючи, використовуючи широкі символи / char16_tрядки! Схоже, компілятор \1у своїй ☺ формі не любить .

f(t,c,d){for(c=7;!(d=t/L"\1<ฐ\1•▼ŭ"[--c]/(c>2?86400:1)););printf("%d %.6s%s\n",d,c*6+(char*)u"敳潣摮業畮整潨牵 慤y†敷步 潭瑮h敹牡",(d<2)+"s");}

Спробуйте в Інтернеті!

Оригінальне рішення

Я розділив масиви на окремі рядки, щоб було легше бачити решту рішення.

char *n[]={"second","minute","hour","day","week","month","year"};
int o[]={1,60,3600,86400,604800,2678400,31536000};
f(int t){int c=7,d;while(!(d=t/o[--c]));printf("%d %s%s\n",d,n[c],d>1?"s":"");}

Спробуйте в Інтернеті!

Запускаючи дільники в порядку від найбільшого до найменшого, ми отримуємо найбільш грубу одиницю часу. Програма погано поводиться, якщо ви даєте їй 0 секунд, але оскільки специфікація явно виключає це значення, я вважаю це прийнятним.


Деякі хитрощі можна використати, щоб зменшити її до 183 байт: Спробуйте в Інтернеті!
гастропнер

1
Вибачте, хто ввів помилку. Правильний на 180 байт: Спробуйте в Інтернеті!
гастропнер

@gastropner Я думаю, що і в останньому є помилка. '(d <1)' має бути '(d <2)' ... або '(d <= 1)', але не може зійти з розуму.
gmatht

@gmatht Ви абсолютно праві!
гастропнер

Добре, останній, обіцяю. 164 байти.
гастропнер


5

Стакс , 54 байти

▀♂♂┼╕Qá◙à*ä∙Φò►⌠╨Ns↔║►πîÇ∙cI≡ªb?δ♪9gΓ╕┬≥‼⌡Öå01:♪EoE╘≡ë

Запустіть і налагоджуйте його

Ось розпаковане, нерозроблене, ascii представлення тієї самої програми.

                            stack starts with total seconds
c60/                        push total minutes to stack
c60/                        ... hours 
c24/                        ... days
Yc7/                        ... weeks
y31/                        ... months
y365/                       ... years
L                           make a list out of all the calculated time units
`)sQP(dr'pk,oV4?_HIFD?x`j   compressed literal for singular forms of unit names
\                           zip totals with names
rF                          foreach pair of total and name (in reverse orer)
  h!C                       skip if the current total is falsey (0)
  _J                        join the total and unit name with a space
  's_1=T+                   concat 's' unless the total is one

Після виконання, оскільки іншого виводу немає, верхня частина стека друкується неявно.

Виконати цей


5

JavaScript (ES6), 131 байт

n=>[60,60,24,7,31/7,365/31,0].map((v,i)=>s=n<1?s:(k=n|0)+' '+'second,minute,hour,day,week,month,year'.split`,`[n/=v,i])|k>1?s+'s':s

Спробуйте в Інтернеті!


Мені не було відомо про синтаксис, який ви використовували (розділити ,). Я дізнався щось нове. Прекрасне рішення.
Макотосан

1
@Makotosan Зауважте, що насправді передається splitмасив [',']. Тому це працює лише з функціями, які примушують примус до рядка.
Арнольд

3

Java 8, 197 195 157 байт

n->(n<60?n+" second":(n/=60)<60?n+" minute":(n/=60)<24?n+" hour":(n/=24)<7?n+" day":n<31?(n/=7)+" week":n<365?(n/=31)+" month":(n/=365)+" year")+(n>1?"s":"")

-38 байт завдяки @ OlivierGrégoire .

Пояснення:

Спробуйте в Інтернеті.

n->               // Method with long parameter and String return-type
  (n<60?          //  If `n` is below 60:
    n             //   Output `n`
    +" second"    //   + " second"
   :(n/=60)<60?   //  Else-if `n` is below 60*60
    n             //   Integer-divide `n` by 60, and output it
    +" minute"    //   + " minute"
   :(n/=60)<24?   //  Else-if `n` is below 60*60*24:
    n             //   Integer-divide `n` by 60*60, and output it
    +" hour"      //   + " hour"
   :(n/=24)<7?    //  Else-if `n` is below 60*60*24*7:
    n             //   Integer-divide `n` by 60*60*24, and output it
    +" day"       //   + " day"
   :n<31?         //  Else-if `n` is below 60*60*24*31:
    (n/=7)        //   Integer-divide `n` by 60*60*24*7, and output it
    +" week"      //   + " week"
   :n<365?        //  Else-if `n` is below 60*60*24*365:
    (n/=31)       //   Integer-divide `n` by 60*60*24*31, and output it
    +" month"     //   + " month"
   :              //  Else:
    (n/=365)      //   Integer-divide `n` by 60*60*24*365, and output it
    +" year")     //   + " year"
   +(n>1?"s":"")  //  And add a trailing (plural) "s" if (the new) `n` is larger than 1

1
157 байт . Я просто переграв ваші номери на більш короткі і перемістився /=там, де потрібно.
Олів'є Грегоар

Особистий фаворит: n->{for(int t=60,d[]={1,t,t*=60,t*=24,t*7,t*31,t*365},x=7;;)if(n>=d[--x])return(n/=d[x])+" "+"second,minute,hour,day,week,month,year".split(",")[x]+(n>1?"s":"");}(162 байти), ймовірно, хороша база для гри в гольф.
Олів'є Грегоар

Збережіть 9 байт, використовуючи n/7+замість (n/=7)+тощо
Ніл

@Neil Боюся, що це не вийде. Наприклад, якщо вхід є 2678400, вихід має бути 1 monthзамість 1 months(однини замість множини).
Кевін Кройсейсен

О, тонке, дякую за те, що ви дали мені знати.
Ніл


2

T-SQL , 306 байт (281 байт без вводу / виводу)

DECLARE @n INT=1
DECLARE @r VARCHAR(30)=TRIM(COALESCE(STR(NULLIF(@n/31536000,0))+' year',STR(NULLIF(@n/2678400,0))+' month',STR(NULLIF(@n/604800,0))+' week',STR(NULLIF(@n/86400,0))+' day',STR(NULLIF(@n/3600,0))+' hour',STR(NULLIF(@n/60,0))+' minute',STR(@n)+' second'))IF LEFT(@r,2)>1 SET @r+='s'
PRINT @r

Дві невеликі помилки: TRIMне визначено, можливо, це має бути LTRIM. Між weekі day, у вас + , можливо, повинен бути,
Стефан Бауер

Дійсно, замість + цього має бути а, ,і я це зараз виправив. Однак TRIMфункція визначена з SQL Server 2017. Дякую.
Разван Сокол

2

R , 157 байт

function(n,x=cumprod(c(1,60,60,24,7,31/7,365/31)),i=cut(n,x),o=n%/%x[i])cat(o," ",c("second","minute","hour","day","week","year")[i],"if"(o>1,"s",""),sep="")

Спробуйте в Інтернеті!

cutце зручно, оскільки він розбиває діапазони на factors, які зберігаються внутрішньо як integers, тобто ми можемо використовувати їх і як індекси масиву. Ми, мабуть, можемо зробити щось трохи розумніші з назвами періоду часу, але я поки що не можу це зрозуміти.


2

APL + WIN, 88 119 байт

Оригінальна версія пропустила тижні та місяці, як вказував Філ Х; (

Запрошує введення екрану кількості секунд

a←⌽<\⌽1≤b←⎕÷×\1 60 60 24 7,(31÷7),365÷31⋄b,(-(b←⌊a/b)=1)↓∊a/'seconds' 'minutes' 'hours' 'days' 'weeks' 'months' 'years'

Пояснення

b←⎕÷×\1 60 60 24 7,(31÷7),365÷31 prompts for input and converts to years, days, hours, minutes, seconds

a←⌽<\⌽1≤b identify largest unit of time and assign it to a

a/'years' 'days' 'hours' 'minutes' 'seconds' select time unit

(-(b←⌊a/b)=1)↓∊ determine if singular if so drop final s in time unit

b, concatenate number of units to time unit from previous steps

Хтось їв тижні та місяці?
Phil H

@PhilH Monster cookie? ;) Спасибі. Відповідь редагували відповідно.
Грем

Це виглядало занадто акуратно, навіть для APL! Також, як ви рахуєте байти? Я рахую 119 символів, а не байти ...
Phil H

@PhilH Я не розумію ваш коментар спочатку ми домовляємось про 119 байт, які я змінив під час редагування відповіді і вище ви не кажете, скільки байтів ви
Грем


1

Пакет, 185 байт

@for %%t in (1.second 60.minute 3600.hour 43200.day 302400.week, 1339200.month, 15768000.year)do @if %1 geq %%~nt set/an=%1/%%~nt&set u=%%~xt
@if %n% gtr 1 set u=%u%s
@echo %n%%u:.= %

1

Python 2 , 146 144 байт

lambda n,d=86400:[`n/x`+' '+y+'s'*(n/x>1)for x,y in zip([365*d,31*d,7*d,d,3600,60,1],'year month week day hour minute second'.split())if n/x][0]

Спробуйте в Інтернеті!

2 байти збережено завдяки Джонатану Аллану


1
if n/xзберігає байт.
Джонатан Аллан

1
Повернення порядку та індексація 0зберігає інше.
Джонатан Аллан




0

Perl 6 / Rakudo 138 байт

Я впевнений, що йти далі, але поки що

{my @d=(365/31,31/7,7,24,60,60);$_/=@d.pop while @d&&$_>@d[*-1];$_.Int~" "~ <year month week day hour minute second>[+@d]~($_>1??"s"!!"")}

Поясніть:

{ # bare code block, implicit $_ input
    my @d=(365/31,31/7,7,24,60,60); # ratios between units
    $_ /= @d.pop while @d && $_ > @d[*-1]; # pop ratios off @d until dwarfed
    $_.Int~   # implicitly output: rounded count
        " "~  # space
        <year month week day hour minute second>[+@d]~ # unit given @d
        ($_>1??"s"!!"")  # plural
}

0

R, 336

Незавершена робота

function(x){
a=cumprod(c(1,60,60,24,7,31/7,365/31))
t=c("second","minute","hour","day","week","month")
e=as.data.frame(cbind(table(cut(x,a,t)),a,t))
y=x%/%as.integer(as.character(e$a[e$V1==1]))
ifelse(x>=a[7],paste(x%/%a[7],ifelse(x%/%a[7]==1,"year","years")),
ifelse(y>1,paste(y,paste0(e$t[e$V1==1],"s")),paste(y,e$t[e$V1==1])))}

0

R , 246 байт

f=function(x,r=as.integer(strsplit(strftime(as.POSIXlt(x,"","1970-01-01"),"%Y %m %V %d %H %M %S")," ")[[1]])-c(1970,1,1,1,1,0,0),i=which.max(r>0)){cat(r[i],paste0(c("year","month","week","day","hour","minute","second")[i],ifelse(r[i]>1,"s","")))}

Спробуйте в Інтернеті!

Для цього використовується форматування часу замість арифметики, просто для чортви. Може, інші могли зробити це меншим?

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.