Wie alt ist es ungefähr?

29

Schreiben Sie ein kurzes Programm, das eine positive Anzahl von Sekunden für ein Alter benötigt und eine Schätzung dieser Zeit auf Englisch ausgibt.

Ihr Programm muss die am wenigsten genaue verstrichene Zeit unter den folgenden Metriken und deren Länge in Sekunden ausgeben :

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

Beispiele

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

Wie Sie oben sehen können, geben wir nach der Zeit von beispielsweise 1 Tag (60 * 60 * 24 = 86400 Sekunden) keine Minute (n) oder Stunde (n) mehr aus , sondern nur noch Tage, bis wir die Zeit von einer Woche überschreiten , und so weiter.

Betrachten Sie die angegebene Zeitspanne als Alter. Zum Beispiel ist nach 119 Sekunden 1 Minute vergangen , nicht 2.

Regeln

  • Keine Angabe für 0 oder negative Eingänge.
  • Folgen Sie der richtigen Pluralisierung. Jedes Maß größer als 1 muss ein sNachfolgen des Wortes enthalten.
  • Sie dürfen keine bereits vorhandene Bibliothek verwenden, die die Funktion des gesamten Programms erfüllt.
  • Dies ist ein Code Golf, das kürzeste Programm gewinnt die Internet Points.
  • Habe Spaß!
ein wenig verwirrt
quelle
3
Ich verstehe nicht, wie wir eine Einheit oder einen Betrag auswählen. Runden wir?
xnor
1
@xnoder wir dividieren ganzzahlig und verwenden den kleinsten Wert ungleich Null zusammen mit seiner Einheit (möglicherweise pluralisiert). Daher 59 -> "59 Sekunden" und 86401 -> "1 Tag".
Jonathan Allan
5
Willkommen bei PPCG! Schöne erste Herausforderung. Zum späteren Nachschlagen gibt es eine Sandbox, die nützlich ist, um vor dem Posten auf main Feedback zu erhalten.
Jonathan Allan
4
Beachten Sie, dass Do X without Y ebenso nicht empfohlen wird wie Non-beobachtbaren Programmanforderung .
user202729
1
Wie sollen wir die Zahlen runden? Sollten 119 Sekunden 1 Minute oder 2 Minuten sein? Was ist mit 90?
user202729

Antworten:

8

Jelly , 62 Bytes

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

Ein volles Programm druckt das Ergebnis aus.
(Als monadische Verknüpfung wird eine Liste mit einer ganzen Zahl gefolgt von Zeichen zurückgegeben.)

Probieren Sie es online!

Wie?

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
quelle
8

C 194, 180 144 128 Zeichen

Vielen Dank an @gastropher für die Code-Kürzungen. Ich habe vergessen, dass C implizite Parameter mit K & R-Funktionen erlaubt! Vielen Dank auch an @gmatht für die Idee, Literale anstelle von Arrays einzufügen. Ich erweitert , dass die Charaktere durch missbrauchen Vorteil von Breitzeichen / Aufnahme char16_tStrings! Der Compiler scheint jedoch nicht \1in seiner Form zu gefallen .

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

Probieren Sie es online!

Originelle Lösung

Ich habe die Arrays in separate Zeilen aufgeteilt, um den Rest der Lösung besser erkennen zu können.

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

Probieren Sie es online!

Wenn wir die Divisoren in der Reihenfolge vom größten zum kleinsten ausführen, erhalten wir die gröbste Zeiteinheit. Das Programm verhält sich falsch, wenn Sie 0 Sekunden eingeben, aber da die Spezifikation diesen Wert ausdrücklich ausschließt, halte ich das für akzeptabel.

ErikF
quelle
Einige Tricks können verwendet werden, um es auf 183 Bytes zu bringen: Probieren Sie es online aus!
Gastropner
1
Entschuldigung, das hat einen Fehler verursacht. Richtige bei 180 Bytes: Probieren Sie es online!
Gastropner
@gastropner Ich denke, der letzte hat auch einen Bug. '(d <1)' sollte '(d <2)' ... oder '(d <= 1)' sein, aber lasst uns nicht verrückt werden.
Samstag,
@gmatht Du hast ganz recht!
Gastropner
OK, letzteres verspreche ich. 164 Bytes.
Gastropner
5

Stax , 54 Bytes

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

Führen Sie es aus und debuggen Sie es

Hier ist die entpackte, ungolfierte ASCII-Darstellung desselben Programms.

                            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

Da es nach der Ausführung keine andere Ausgabe gibt, wird implizit die Oberseite des Stapels gedruckt.

Führen Sie dieses aus

rekursiv
quelle
5

JavaScript (ES6), 131 Byte

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

Probieren Sie es online!

Arnauld
quelle
Die von Ihnen verwendete Syntax (split ,) war mir nicht bekannt . Ich habe etwas Neues gelernt. Großartige Lösung.
Makotosan
1
@Makotosan Beachten Sie, dass splitdas Array tatsächlich übergeben wird [',']. Daher funktioniert dies nur mit Funktionen, die einen Zwang zu einer Zeichenfolge erzwingen.
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 dank @ OlivierGrégoire .

Erläuterung:

Probieren Sie es online aus.

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
quelle
1
157 Bytes . Ich habe nur Ihre Zahlen zu kürzeren Golf gespielt und bin umgezogen, /=wo es nötig war.
Olivier Grégoire
Persönlicher Favorit: 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), wahrscheinlich eine gute Basis zum Golfen.
Olivier Grégoire
Speichern Sie 9 Bytes mit n/7+anstelle von (n/=7)+etc.
Neil
@Neil Ich fürchte, das wird nicht funktionieren. Wenn zum Beispiel die Eingabe ist 2678400, sollte die Ausgabe 1 monthstatt 1 months(Singular statt Plural) sein.
Kevin Cruijssen
Oh, subtil, danke, dass du mich informiert hast.
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 ""}"}

Probieren Sie es online!

Makotosan
quelle
2

T-SQL , 306 Byte (281 Byte ohne E / A)

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
quelle
Zwei kleine Tippfehler: Ist TRIMnicht definiert, sollte dies evtl. sein LTRIM. Zwischen weekund day, Sie haben eine + , sollte möglicherweise eine sein,
Stephan Bauer
Tatsächlich sollte es stattdessen + ein sein ,und das habe ich jetzt korrigiert. Die TRIMFunktion ist jedoch seit SQL Server 2017 definiert. Danke.
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="")

Probieren Sie es online!

cutist praktisch, da es Bereiche in factors aufteilt , die intern als integers gespeichert werden , was bedeutet, dass wir sie auch als Array-Indizes verwenden können. Wir können mit den Zeitperiodennamen wahrscheinlich etwas schlaueres machen, aber ich kann es noch nicht herausfinden.

Giuseppe
quelle
2

APL + WIN, 88 119 Bytes

Die Originalfassung verpasste Wochen und Monate, wie von Phil H. ausgeführt.

Fordert die Bildschirmeingabe in Sekunden an

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'

Erläuterung

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
quelle
Hat jemand die Wochen und Monate gegessen?
Phil H
@ PhilH Cookie-Monster? ;) Vielen Dank. Antwort entsprechend bearbeitet.
Graham
Es sah auch für APL zu ordentlich aus! Wie zählen Sie die Bytes? Ich zähle 119 Zeichen anstatt Bytes ...
Phil H
@PhilH Ich verstehe Ihren Kommentar nicht zuerst, wir sind uns einig über 119 Bytes, die ich bei der Bearbeitung der Antwort geändert habe, und darüber sagen Sie nicht, wie viele Bytes Sie in Frage stellen
Graham
1

JavaScript (Node.js) , 177 Byte

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

Probieren Sie es online!

Makotosan
quelle
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:.= %
Neil
quelle
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]

Probieren Sie es online!

Jonathan Allan hat 2 Bytes gespart

Chas Brown
quelle
1
if n/xSpeichert ein Byte.
Jonathan Allan
1
Wenn Sie die Reihenfolge umkehren und mit indizieren, wird ein 0anderer gespeichert.
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;

Probieren Sie es online!

Jo.
quelle
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))"

Probieren Sie es online!

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

Probieren Sie es online!

Asone Tuhid
quelle
0

Perl 6 / Rakudo 138 Bytes

Ich bin mir sicher, dass es noch weiter geht, aber fürs Erste

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

Erläutern:

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

R 336

In Bearbeitung

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

Probieren Sie es online!

Dies ist die Verwendung von Zeitformatierung anstelle von Arithmetik, nur zum Teufel. Vielleicht könnten andere das kleiner machen?

niczky12
quelle