¿Qué edad tiene aproximadamente?

29

Escriba un programa corto que tome un número positivo de segundos que represente una edad y genere una estimación de ese tiempo en inglés.

Su programa debe generar la cantidad de tiempo menos precisa que haya pasado, entre las siguientes métricas y sus duraciones en segundos:

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

Ejemplos

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

Como puede ver arriba, después del tiempo de decir, 1 día (60 * 60 * 24 = 86400 segundos), ya no emitimos minutos u horas , sino solo días hasta que superamos el tiempo de una semana , y así.

Considere la cantidad de tiempo dada para ser una edad. Por ejemplo, después de 119 segundos, ha pasado 1 minuto , no 2.

Reglas

  • Sin especificación para 0 o entradas negativas.
  • Sigue la pluralización adecuada. Cada medida mayor que 1 debe incluir un sseguimiento de la palabra.
  • No puede utilizar una biblioteca preexistente que cumple la función de todo el programa.
  • Este es un código de golf, el programa más corto gana los puntos de internet.
  • ¡Que te diviertas!
poco confundido
fuente
3
No entiendo cómo elegimos una unidad o cantidad. ¿Redondeamos?
xnor
1
@xnor dividimos enteros y usamos el valor más pequeño distinto de cero junto con su unidad (posiblemente en plural). De ahí 59 -> "59 segundos" y 86401 -> "1 día".
Jonathan Allan
55
Bienvenido a PPCG! Bonito primer desafío. Para referencia futura, hay un sandbox que es útil para obtener comentarios antes de publicar en main.
Jonathan Allan
44
Tenga en cuenta que no se recomienda hacer X sin Y , así como el requisito de programa no observable .
user202729
1
¿Cómo debemos redondear los números? ¿Deberían 119 segundos ser 1 minuto o 2 minutos? ¿Qué hay de 90?
user202729

Respuestas:

8

Jalea , 62 bytes

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

Un programa completo que imprime el resultado.
(Como enlace monádico, devuelve una lista de un entero seguido de caracteres)

Pruébalo en línea!

¿Cómo?

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"
Jonathan Allan
fuente
8

C, 194 , 180, 144, 128 caracteres

Gracias a @gastropher por las reducciones de código. ¡Olvidé que C permite parámetros implícitos usando funciones de estilo K&R! También gracias a @gmatht por la idea de poner literales dentro en lugar de matrices. ¡Extendí eso a los personajes abusando de aprovechar caracteres / char16_tcadenas anchas ! Sin embargo, al compilador no parece gustarle \1en su forma ☺.

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

Pruébalo en línea!

Solución original

Dividí las matrices en líneas separadas para que sea más fácil ver el resto de la solución.

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

Pruébalo en línea!

Al ejecutar los divisores en orden de mayor a menor, obtenemos la unidad de tiempo más gruesa. El programa se comporta mal si le das 0 segundos, pero como la especificación excluye explícitamente este valor, considero que es aceptable.

ErikF
fuente
Se pueden usar algunos trucos para reducirlo a 183 bytes: ¡ Pruébelo en línea!
Gastropner
1
Lo siento, ese introdujo un error. Uno adecuado a 180 bytes: ¡ Pruébelo en línea!
Gastropner
@gastropner Creo que el último también tiene un error. '(d <1)' debería ser '(d <2)' ... o '(d <= 1)', pero no nos volvamos locos.
gmatht
@gmatht Tienes toda la razón!
Gastropner
OK, el último, lo prometo. 164 bytes.
Gastropner
7

Perl 5 , 110 bytes

year31536000month2678400week604800day86400hour3600minute60second1=~s:\D+:say"$% $&",$_=$%>1&&"s"if$%=$_/$':reg

Pruébalo en línea!

Ton Hospel
fuente
5

Stax , 54 bytes

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

Ejecutar y depurarlo

Aquí está la representación ascii desempaquetada, sin golf, del mismo programa.

                            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

Después de la ejecución, dado que no hay otro resultado, la parte superior de la pila se imprime implícitamente.

Ejecute este

recursivo
fuente
5

JavaScript (ES6), 131 bytes

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

Pruébalo en línea!

Arnauld
fuente
No estaba al tanto de la sintaxis que usaste (dividir ,). Aprendí algo nuevo. Gran solución
Makotosan
1
@Makotosan Tenga en cuenta que lo que realmente se pasa a splitla matriz [',']. Por lo tanto, esto solo funciona con funciones que fuerzan la coerción a una cadena.
Arnauld
3

Java 8, 197 195 157 bytes

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 bytes gracias a @ OlivierGrégoire .

Explicación:

Pruébalo en línea.

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
Kevin Cruijssen
fuente
1
157 bytes . Acabo de comparar tus números con los más cortos y me moví /=donde era necesario.
Olivier Grégoire
Favorito personal: 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 bytes), probablemente una buena base para jugar al golf.
Olivier Grégoire
Ahorre 9 bytes usando en n/7+lugar de (n/=7)+etc.
Neil
@Neil, me temo que eso no funcionará. Por ejemplo, si la entrada es 2678400, la salida debería ser en 1 monthlugar de 1 months(singular en lugar de plural).
Kevin Cruijssen
Oh, sutil, gracias por hacérmelo saber.
Neil
2

Kotlin , 205 203 196 bytes

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

Pruébalo en línea!

Makotosan
fuente
2

T-SQL , 306 bytes (281 bytes sin E / S)

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
Razvan Socol
fuente
Dos pequeños errores tipográficos: TRIMno está definido, esto posiblemente debería ser LTRIM. Entre weeky day, usted tiene un + , posiblemente debería ser un,
Stephan Bauer
De hecho, en lugar de + eso debería ser ,ay lo corregí ahora. Sin embargo, la TRIMfunción está definida desde SQL Server 2017. Gracias.
Razvan Socol
2

R , 157 bytes

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="")

Pruébalo en línea!

cutes útil, ya que divide los rangos en factors, que se almacenan internamente como integers, lo que significa que también podemos usarlos como índices de matriz. Probablemente podamos hacer algo un poco más inteligente con los nombres de los períodos de tiempo, pero todavía no puedo entenderlo.

Giuseppe
fuente
2

APL + ganar, 88 119 bytes

La versión original se perdió semanas y meses como lo señaló Phil H; (

Solicita la entrada en pantalla del número de segundos

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'

Explicación

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
Graham
fuente
¿Alguien comió las semanas y los meses?
Phil H
@PhilH ¿Monstruo de las galletas? ;) Gracias. Respuesta editada en consecuencia.
Graham
¡Parecía demasiado ordenado, incluso para APL! Además, ¿cómo estás contando los bytes? Cuento 119 caracteres en lugar de bytes ...
Phil H
@PhilH No entiendo tu comentario primero, estamos de acuerdo en 119 bytes que cambié al editar la respuesta y arriba no dices cuántos bytes estás cuestionando
Graham
1

JavaScript (Node.js) , 177 bytes

x=>{return d=86400,v=[[d*365,'year'],[d*31,'month'],[d*7,'week'],[d,'day'],[3600,'hour'],[60,'minute'],[1,'second']].find(i=>x>=i[0]),c=parseInt(x/v[0]),c+' '+v[1]+(c>1?'s':'')}

Pruébalo en línea!

Makotosan
fuente
1

Lote, 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:.= %
Neil
fuente
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]

Pruébalo en línea!

2 bytes guardados gracias a Jonathan Allan

Chas Brown
fuente
1
if n/xGuarda un byte.
Jonathan Allan
1
Invertir el orden e indexar con 0guarda otro.
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;

Pruébalo en línea!

Jo
fuente
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))"

Pruébalo en línea!

niczky12
fuente
0

Rubí , 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}"}

Pruébalo en línea!

Asone Tuhid
fuente
0

Perl 6 / Rakudo 138 bytes

Estoy seguro de que hay más por recorrer, pero por ahora

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

Explicar:

{ # 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
}
Phil H
fuente
0

R, 336

Trabajo en progreso

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])))}
Riccardo Camon
fuente
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","")))}

Pruébalo en línea!

Esto está usando el formateo del tiempo en lugar de la aritmética, solo por el placer de hacerlo. ¿Quizás otros podrían hacer esto más pequeño?

niczky12
fuente