Сколько лет это примерно?

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следующее слово.
  • Вы не можете использовать ранее существующую библиотеку, которая выполняет функции всей программы.
  • Это код гольф, самая короткая программа выигрывает очки интернета.
  • Повеселись!
bitconfused
источник
3
Я не понимаю, как мы выбираем единицу или сумму. Мы вокруг?
xnor
1
@xnor мы делим целое число и используем наименьшее ненулевое значение вместе с его единицей (возможно, во множественном числе). Отсюда 59 -> «59 секунд» и 86401 -> «1 день».
Джонатан Аллан
5
Добро пожаловать в PPCG! Хороший первый вызов. Для дальнейшего использования есть песочница, которая полезна для получения обратной связи перед отправкой на главную.
Джонатан Аллан
4
Обратите внимание, что Do X без Y не рекомендуется, а также ненаблюдаемые требования программы .
user202729
1
Как мы должны округлить числа? 119 секунд должно быть 1 минута или 2 минуты? Как насчет 90?
user202729

Ответы:

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 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 секунд, но, поскольку спецификация явно исключает это значение, я считаю это приемлемым.

ErikF
источник
Некоторые приемы могут быть использованы для уменьшения его до 183 байт: попробуйте онлайн!
гастропнер
1
Извините, этот внес ошибку. Надлежащий на 180 байтов: попробуйте онлайн!
гастропнер
@gastropner Я думаю, у последнего тоже есть ошибка. '(d <1)' должно быть '(d <2)' ... или '(d <= 1)', но давайте не будем сходить с ума.
Gmatht
@gmatht Вы совершенно правы!
gastropner
Хорошо, последний, я обещаю. 164 байта.
gastropner
5

Stax , 54 байта

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

Запустите и отладьте его

Вот распакованное, ungolfed, 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

Попробуйте онлайн!

Arnauld
источник
Я не знал о синтаксисе, который вы использовали (split ,). Я узнал что-то новое. Отличное решение.
Макотосан
1
@Makotosan Обратите внимание, что на самом деле передается splitмассив [',']. Следовательно, это работает только с функциями, которые принудительно приводят к строке.
Арно
3

Ява 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)+и т. Д.
Нейл
@ Боюсь, это не сработает. Например, если входное значение есть 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, что означает, что мы можем использовать их также как индексы массива. Возможно, мы можем сделать что-то более умное с именами периодов времени, но я пока не могу понять это.

Giuseppe
источник
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
Грэхем
источник
Кто-то ел недели и месяцы?
Фил Х
@PhilH Cookie монстр? ;) Благодарность. Ответ отредактирован соответственно.
Грэм
Это выглядело слишком аккуратно, даже для APL! Кроме того, как ты считаешь байты? Я считаю 119 символов, а не байтов ...
Фил Х
@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сохранением другого.
Джонатан Аллан
1

PHP , 183 байта

<?$a=[second=>$l=1,minute=>60,hour=>60,day=>24,week=>7,month=>31/7,year=>365/31];foreach($a as$p=>$n){$q=$n*$l;if($q<=$s=$argv[1])$r=($m=floor($s/$q))." $p".($m>1?s:"");$l=$q;}echo$r;

Попробуйте онлайн!

Джо.
источник
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","")))}

Попробуйте онлайн!

Это использует форматирование времени вместо арифметики, просто для этого. Может быть, другие могли бы сделать это меньше?

niczky12
источник