Quel âge a-t-il à peu près?

29

Écrivez un programme court qui prend un nombre positif de secondes représentant un âge et produit une estimation de ce temps en anglais.

Votre programme doit générer le temps le moins précis qui s'est écoulé, parmi les mesures suivantes et leur durée en secondes:

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

Exemples

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

Comme vous pouvez le voir ci-dessus, après le temps de dire 1 jour (60 * 60 * 24 = 86400 secondes), nous ne produisons plus de minute (s) ou d'heure (s) , mais seulement des jours avant de dépasser le temps d'une semaine , etc.

Considérez la durée donnée comme un âge. Par exemple, après 119 secondes, 1 minute s'est écoulée , pas 2.

Règles

  • Aucune spécification pour 0 ou entrées négatives.
  • Suivez la bonne pluralisation. Chaque mesure supérieure à 1 doit inclure un ssuivant le mot.
  • Vous ne pouvez pas utiliser une bibliothèque préexistante qui remplit la fonction de l'ensemble du programme.
  • Il s'agit d'un code de golf, le programme le plus court remporte les points Internet.
  • S'amuser!
Un peu confus
la source
3
Je ne comprends pas comment nous choisissons une unité ou un montant. On tourne?
xnor
1
@xnor nous divisons un entier et utilisons la plus petite valeur non nulle avec son unité (éventuellement pluralisée). D'où 59 -> "59 secondes" et 86401 -> "1 jour".
Jonathan Allan
5
Bienvenue chez PPCG! Beau premier défi. Pour référence future, il existe un bac à sable qui est utile pour obtenir des commentaires avant de publier sur le site principal.
Jonathan Allan
4
Notez que Do X sans Y est déconseillé, ainsi que l'exigence de programme non observable .
user202729
1
Comment arrondir les chiffres? Est-ce que 119 secondes devraient être 1 minute ou 2 minutes? Et 90?
user202729

Réponses:

8

Gelée , 62 octets

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

Un programme complet imprimant le résultat.
(En tant que lien monadique, il renvoie une liste d'un entier suivi de caractères)

Essayez-le en ligne!

Comment?

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
la source
8

C, 194 180 144 128 caractères

Merci à @gastropher pour les réductions de code. J'ai oublié que C permet des paramètres implicites en utilisant des fonctions de style K & R! Merci également à @gmatht pour l'idée de mettre des littéraux à l'intérieur au lieu de tableaux. J'ai étendu cela aux personnages en abusant en profitant des caractères / char16_tchaînes larges ! Le compilateur ne semble cependant pas aimer \1sa forme ☺.

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

Essayez-le en ligne!

Solution originale

J'ai divisé les tableaux en lignes distinctes pour faciliter la visualisation du reste de la solution.

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

Essayez-le en ligne!

En exécutant les diviseurs dans l'ordre du plus grand au plus petit, nous obtenons l'unité de temps la plus grossière. Le programme se comporte mal si vous lui donnez 0 seconde, mais comme la spécification exclut explicitement cette valeur, je considère que cela est acceptable.

ErikF
la source
Quelques astuces peuvent être utilisées pour le réduire à 183 octets: Essayez-le en ligne!
gastropner
1
Désolé, celui-ci a introduit un bug. Un bon à 180 octets: Essayez-le en ligne!
gastropner
@gastropner Je pense que le dernier a aussi un bug. '(d <1)' devrait être '(d <2)' ... ou '(d <= 1)', mais ne soyons pas fous.
gmatht
@gmatht Vous avez tout à fait raison!
gastropner
OK, le dernier, je le promets. 164 octets.
gastropner
7

Perl 5 , 110 octets

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

Essayez-le en ligne!

Ton Hospel
la source
5

Stax , 54 octets

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

Exécuter et déboguer

Voici la représentation ascii non emballée et non golfée du même programme.

                            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

Après l'exécution, puisqu'il n'y a pas d'autre sortie, le haut de la pile est imprimé implicitement.

Exécutez celui-ci

récursif
la source
5

JavaScript (ES6), 131 octets

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

Essayez-le en ligne!

Arnauld
la source
Je ne connaissais pas la syntaxe que vous avez utilisée (split ,). J'ai appris quelque chose de nouveau. Excellente solution.
Makotosan
1
@Makotosan Notez que ce qui est réellement passé splitest le tableau [',']. Par conséquent, cela ne fonctionne qu'avec les fonctions qui forcent la coercition sur une chaîne.
Arnauld
3

Java 8, 197 195 157 octets

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 octets grâce à @ OlivierGrégoire .

Explication:

Essayez-le en ligne.

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
la source
1
157 octets . Je viens de jouer vos numéros à des numéros plus courts et de me déplacer /=là où c'était nécessaire.
Olivier Grégoire
Favori personnel: 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 octets), probablement une bonne base pour le golf.
Olivier Grégoire
Économisez 9 octets en utilisant n/7+au lieu de (n/=7)+etc.
Neil
@Neil J'ai peur que ça ne marche pas. Par exemple, si l'entrée est 2678400, la sortie doit être à la 1 monthplace de 1 months(singulier au lieu de pluriel).
Kevin Cruijssen
Oh, subtile, merci de me l'avoir fait savoir.
Neil
2

Kotlin , 205 203 196 octets

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

Essayez-le en ligne!

Makotosan
la source
2

T-SQL , 306 octets (281 octets sans 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
la source
Deux petites fautes de frappe: TRIMn'est pas définie, cela devrait l'être LTRIM. Entre weeket day, vous avez un + , devrait éventuellement être un,
Stephan Bauer
En effet, au lieu de + cela devrait être un ,et je l'ai corrigé maintenant. Cependant, la TRIMfonction est définie depuis SQL Server 2017. Merci.
Razvan Socol
2

R , 157 octets

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

Essayez-le en ligne!

cutest pratique, car il divise les plages en factors, qui sont stockées en interne en tant que integers, ce qui signifie que nous pouvons également les utiliser comme indices de tableau. Nous pouvons probablement faire quelque chose d'un peu plus intelligent avec les noms de période, mais je ne peux pas encore le comprendre.

Giuseppe
la source
2

APL + WIN, 88 119 octets

La version originale a manqué des semaines et des mois, comme l'a souligné Phil H; (

Demande à l'écran la saisie du nombre de secondes

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'

Explication

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
la source
Quelqu'un a-t-il mangé les semaines et les mois?
Phil H
@PhilH Cookie monster? ;) Merci. Réponse modifiée en conséquence.
Graham
Ça avait l'air trop soigné, même pour APL! De plus, comment comptez-vous les octets? Je compte 119 caractères plutôt que des octets ...
Phil H
@PhilH Je ne comprends pas votre commentaire d'abord nous sommes d'accord sur 119 octets que j'ai modifiés lors de l'édition de la réponse et surtout vous ne dites pas combien d'octets vous interrogez
Graham
1

JavaScript (Node.js) , 177 octets

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':'')}

Essayez-le en ligne!

Makotosan
la source
1

Lot, 185 octets

@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
la source
1

Python 2 , 146 144 octets

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]

Essayez-le en ligne!

2 octets économisés grâce à Jonathan Allan

Chas Brown
la source
1
if n/xenregistre un octet.
Jonathan Allan
1
Inverser l'ordre et l'indexation avec 0enregistre un autre.
Jonathan Allan
1

PHP , 183 octets

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

Essayez-le en ligne!

Jo.
la source
1

Julia 0,6 , 161 octets

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

Essayez-le en ligne!

niczky12
la source
0

Rubis , 129 octets

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

Essayez-le en ligne!

Asone Tuhid
la source
0

Perl 6 / Rakudo 138 octets

Je suis sûr qu'il y a encore du chemin à parcourir, mais pour l'instant

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

Expliquez:

{ # 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
la source
0

R, 336

Travail en cours

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
la source
0

R , 246 octets

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

Essayez-le en ligne!

Cela utilise le formatage du temps au lieu de l'arithmétique, juste pour l'enfer. Peut-être que d'autres pourraient réduire cela?

niczky12
la source