大概几岁了?


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!不错的第一个挑战。供以后参考,有一个沙箱,对于在发布到main之前获取反馈很有用。
乔纳森·艾伦,


1
我们应该如何对数字进行四舍五入?119秒应该是1分钟还是2分钟?那90呢?
user202729 '18

Answers:


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​​秒,该程序就会出现异常,但是由于规范中明确排除了该值,因此我认为这是可以接受的。


可以使用一些技巧将其减少到183个字节:在线尝试!
gastropner

1
对不起,那个人引入了一个错误。180字节正确的一个:在线尝试!
gastropner

@gastropner我认为最后一个也有错误。'(d <1)'应该是'(d <2)'...或'(d <= 1)',但不要发疯。
gmatht

@gmatht你说得对!
gastropner

好,最后一个,我保证。164个字节。
gastropner


5

Stax,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

在线尝试!


我不知道您使用的语法(split ,)。我学到新东西。很好的解决方案。
Makotosan

1
@Makotosan注意,实际上传递给的split是数组[',']。因此,这仅适用于强制强制字符串的函数。
Arnauld

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

科特林205个 203 196字节

x->val d=86400
with(listOf(1 to "second",60 to "minute",3600 to "hour",d to "day",d*7 to "week",d*31 to "month",d*365 to "year").last{x>=it.first}){val c=x/first
"$c ${second+if(c>1)"s" else ""}"}

在线尝试!


2

T-SQL 306字节(不带I / O的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未定义,可能应该是LTRIMweek和之间day,您有一个+ ,可能应该是,
Stephan Bauer

确实,不是+ 应该而是a ,,我现在纠正了这一点。但是,该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字节

菲尔·H(Phil H)指出,原始版本错过了几周和几个月的时间;(

提示屏幕输入秒数

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 Cookie怪物?;) 谢谢。答案进行了相应的编辑。
Graham

看起来太整洁,即使对于APL!另外,如何计算字节数?我数了119个字符而不是字节...
Phil H

@PhilH首先,我不理解您的评论,我们同意我在编辑答案时更改的119个字节,上面您没有说您要查询多少个字节
Graham


1

Batch, 185 bytes

@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 bytes

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]

Try it online!

2 bytes saved thanks to Jonathan Allan


1
if n/x saves a byte.
Jonathan Allan

1
Reversing the order and indexing with 0 saves another.
Jonathan Allan

1

PHP, 183 bytes

<?$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;

Try it online!


1

Julia 0.6, 161 bytes

f(n,d=cumprod([1,60,60,24,7,31/7,365/31]),r=div.(n,d),i=findlast(r.>=1),l=Int(r[i]))="$l $(split("second minute hour day week month year",' ')[i])$("s"^(l>1*1))"

Try it online!


0

Ruby, 129 bytes

->n{x=[365*d=24*k=3600,d*31,d*7,d,k,60,1].index{|j|0<d=n/k=j};"#{d} #{%w{year month week day hour minute second}[x]}#{d>1??s:p}"}

Try it online!


0

Perl 6/Rakudo 138 bytes

I'm sure there's further to go, but for now

{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"!!"")}

Explicate:

{ # 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

Working in progress

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 bytes

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

Try it online!

This is using time formating instead of arithemtics, just for the hell of it. Maybe others could make this smaller?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.