Somma le durate


18

Sfida

Scrivi il codice più breve che può sommare tutte le durate che compaiono nello stdin. Il programma deve considerare solo le stringhe che corrispondono a uno dei seguenti schemi e ignorare il resto.

    HH:MM:SS     (it will be interpreted as HH hours, MM minutes and SS seconds)        
    H:MM:SS      (it will be interpreted as H hours, MM minutes and SS seconds)
    MM:SS        (it will be interpreted as MM minutes, SS seconds)
    M:SS         (it will be interpreted as M minutes, SS seconds)

esempi di stringhe che corrispondono ai modelli enumerati:

    12:00:01  
    2:03:22  
    00:53  
    9:13

L'output dovrebbe essere nella forma

    HHh MMm SSs      (that means HH hours, MM minutes and SS seconds with non-zero-padding)

Esempio

STDIN

Guarda il video di benvenuto.
Video: 10:37 min.
Guarda il video introduttivo al corso.
Video: 3:30 min. Guarda il video su come utilizzare la Panoramica della lezione.
Video: 9:13 min.
Guarda la panoramica video su come utilizzare il sistema Epsilen per condividere il tuo lavoro.
Video: 03:15 min.
Guarda il video per conoscere la valutazione della preparazione accademica dello Stato del Texas (STAAR).
Video: 1:05:26 min.

STDOUT

1h 32m 1s


E le stringhe come 10:4:56? Secondo le specifiche attuali devono essere trattati come 4m 56s, parte 10verrà ignorata. Stessa domanda su 10:12:7cosa significa 10m 12signorare 7? O la gestione di tali stringhe può essere definita come implementazione?
Qwertiy,

Il programma dovrebbe considerare solo le durate del tempo con zero padding nei campi minuto e secondo. Nel tuo esempio la stringa "10: 4: 56" verrà trattata come 4m 56s. Anche la stringa "10: 12: 7" verrà interpretata come 10m 12s.
Alfredo Diaz,

Strano, ma ok :)
Qwertiy l'

Come hai ottenuto 1h 19m 18sl'output? 37+30+13+15+26==121, 10+3+9+3+5==30, 1==1, Quindi mi aspetto 1h 32m 01s. Cosa c'è di sbagliato in questa logica? Inoltre, tale formato di output è quello previsto, no?
Qwertiy,

Hai ragione. Scusa: S
Alfredo Diaz,

Risposte:


3

Pyth 105

K"smh"J"\D\D+|\d+:(?=\d:)|:\d\D"W:QJ1=Q:QJd;FN_msdCfn2lTm+*]0</k\:2msbck\:cQ)~k+d+hK_`%+NZ60=Z/N60=KtK;_k

Provalo online.

Ciò richiede input da STDIN nello stesso modo della risposta Javascript, come testo citato con newline come \ns.

Campione:

"View the Welcome video.\nVideo: 10:37 min.\nView the video introduction to the course.\nVideo: 3:30 min. View the video of how to use the Lesson Overview.\nVideo: 9:13 min.\nView the video overview of how to use the Epsilen system to share your work.\nVideo: 03:15 min.\nView the video to learn about the State of Texas Assessment of Academic Readiness (STAAR).\nVideo: 1:05:26 min."

Produzione

1h 32m 1s

Esempio di lavoro con date più strane:

"10:10:5 and 5:1:10 and 27 or 16: or 1:1:1 or 11:1\n"

Produzione

0h 11m 20s

(Solo le 10:10 e le 1:10 sono tempi legittimi)

Il motivo principale per cui è così lungo è che Pyth non ti consente di estrarre corrispondenze positive. Questo invece corrisponde a tutto ciò che non è un tempo valido e lo sostituisce con un carattere spazio. Quindi, la divisione su spazi bianchi lascia solo tempi e alcuni numeri ribelli. I numeri in eccesso vengono rimossi controllando la presenza di :caratteri, che saranno stati rimossi da tempi non validi. Questo potrebbe quasi certamente essere ulteriormente risolto;)


Bastardo fortunato che ha Pyth regex troppo !
Ottimizzatore

@Optimizer: D È stato un vero dolore però. Sto pensando di suggerire di cambiare il comportamento "is match" per cambiare in base all'arg che gli dai (attualmente controlla solo che non è una stringa)
FryAmTheEggman

6

Javascript ES6, 138 caratteri

Funzione, 139

Accetta la stringa come argomento e scrive l'output sulla console:

f=s=>(r=0,s.replace(/(\d\d?):(\d\d)(:(\d\d))?/g,(m,a,b,x,c)=>r+=x?+c+b*60+a*3600:+b+a*60),console.log("%dh %dm %ds",r/3600,r%3600/60,r%60))

Programma, 138

prompt(r=0).replace(/(\d\d?):(\d\d)(:(\d\d))?/g,(m,a,b,x,c)=>r+=x?+c+b*60+a*3600:+b+a*60),console.log("%dh %dm %ds",r/3600,r%3600/60,r%60)

Test per la funzione

f("View the Welcome video.\n\
Video: 10:37 min.\n\
View the video introduction to the course.\n\
Video: 3:30 min. View the video of how to use the Lesson Overview.\n\
Video: 9:13 min.\n\
View the video overview of how to use the Epsilen system to share your work.\n\
Video: 03:15 min.\n\
View the video to learn about the State of Texas Assessment of Academic Readiness (STAAR).\n\
Video: 1:05:26 min.")

Produzione

"1h 32m 1s"

Ok. Funziona bene in Firefox Developer Edition 36.0a2, la formattazione fallisce solo in Firefox 34.0.
arte

Promt non consente stringhe multilinea. Ma posso aggiungere la versione con prompt () chiamata nello stesso numero di caratteri :) L'ho anche abbreviato di 1 simbolo)))
Qwertiy l'

@Optimizer Come inserirli?
Qwertiy,

@Optimizer L'inserimento di una nuova riga non funziona nel mio FF 35.0.
Qwertiy,

Non riesco a farlo funzionare. L'ho provato su ideone.com ideone.com/56EHgV
Alfredo Diaz l'

4

JavaScript, ES6, 208 200 197 byte

So che questo è molto lungo, ma volevo esplorare le ultime funzionalità di ES6, inversione, riduzione della mappa, funzioni delle frecce e comprensione dell'array (operatore di diffusione).

alert(prompt().match(/\d\d?:\d\d(:\d\d)?/g).map(x=>[...x.split(":").reverse(),z=0].slice(0,3)).reduce((a,b)=>b.map((y,i)=>+y+ +a[i])).map((x,i)=>(z=(t=x+z|0)/60,t%60+"smh"[i])).reverse().join(" "))

Basta eseguire lo snippet in un ultimo Firefox.

Come funziona (ungolfed un po ')

alert(                              // Alert the final result
  prompt()                          // Take the input via prompt
  .match(/\d\d?:\d\d(:\d\d)?/g)     // Match only correct time formats
  .map(                             // Map all matches using this method
    x=>[                            // Take each element as argument x
      ...x.split(":").reverse(),    // split x on ":" and reverse the array, then spread it
      z=0                           // put 0 as last element of return array
    ].slice(0,3)                    // Take only first 3 elements of the array
  ).reduce(                         // Reduce the result using this method
    (a,b)=>                         // Pairwise elements of the array
    b.map(                          // Map array b
      (y,i)=>~~y+~~a[i]             // Convert b[i] to b[i]+a[i]
    )                               // Now we have array like [SS, MM, HH]
  ).map(                            // Map these three values for carry over calculation
    (x,i)=>(
      t=x+z,                        // z contains carryover amount, add it to this value
      z=(t/60)|0,                   // Carryover is now floor(t/60)
      t%60+"smh"[i]                 // Remove overflow from t and add "s", "m" or "h"
    )                               // Now we have array like ["SSs", "MMm", "HHh"]
  ).reverse().join(" ")             // Reverse it and join by space
)

4

Bash (con grep, sed, awk e data): 124 byte, 120 byte

Basta inserire il testo in questo:

grep -o '[:0-9]*'|sed 's/^[^:]*:[^:]*$/:\0/'|awk -F: '{T+=3600*$1+60*$2+$3}END{print"@"T}'|xargs date +"%Hh %Mm %Ss" -ud

Come funziona

  • grep: genera stringhe dall'input contenente solo 0123456789:
  • sed: trasforma MM: SS e M: SS in: M: SS
  • awk: calcola i secondi, la stringa vuota è 0
  • xargs: passa l'input come argomento fino ad oggi
  • data: converte i secondi dall'epoca (con il prefisso @) nel formato richiesto

Quest'ora non è correlata al tuo fuso orario?
Qwertiy,

Hai ragione, bella cattura :) Aggiunto -u flag.
Pgy

3

Perl - 228 201

use integer;$h=0,$m=0,$s=0;while(<>){if(/(\d+:){1,2}\d+/){@a=reverse(split(/:/,$&));push @a,(0)x(3-@a);$s+=@a[0];$m+=@a[1];$h+=@a[2];}}$m+=$s/60;$s=$s%60;$h+=$m/60;$m=$m%60;print $h."h ".$m."m ".$s."s"

Capita di essere lo stesso algoritmo di Optimizer (grep, split, reverse, add).

Non sono un esperto del Perl, quindi forse il conteggio dei byte può essere ridotto.

Ungolfed

use integer;                              # will do integer division
$h=0,$m=0,$s=0;
while(<>){
    if(/(\d+:){1,2}\d+/) {                # extract date formats
        @a = reverse(split(/:/,$&));      # split by ":" and reverse
        push @a,(0)x(3-@a);               # pad with zeros (minutes and hours)
        $s+=@a[0];                        # sum seconds
        $m+=@a[1];                        # sum minutes
        $h+=@a[2];                        # sum hours
    }
}

# convert seconds as minutes    
$m += $s / 60;
$s = $s % 60;

# convert minutes as hours
$h += $m / 60;
$m = $m % 60;

print $h."h ".$m."m ".$s."s";

Per quanto mi riguarda, è strano vedere una soluzione perl più lunga di quella javascript :)
Qwertiy,

Bene, se viene conteggiato anche lo shebang, è normale che sia più lungo.
arte

@Qwertiy sono d'accordo. La mia speranza è che qualche guru del Perl mi aiuti a risolverlo.
coredump,

@manatwork Perché conta?
Qwertiy,

@Qwertiy, perché coredump ha dimenticato di escluderlo dal conteggio. : S Potrebbe essere stato rimosso (insieme a tutte quelle myparole chiave).
arte

3

Rebol - 174

n: charset"1234567890"a:[1 2 n]b:[":"2 n]c: 0 parse input[any[copy x[a b b](c: c + do x)| copy x[a b](c: c + do join"0:"x)| skip]]print reword"$1h $2m $3s"[1 c/1 2 c/2 3 c/3]

Ungolfed + annotato:

n: charset "1234567890"                      ; setup \d regex equiv
a: [1 2 n]                                   ; parse rule for \d{1,2} 
b: [":" 2 n]                                 ; parse rule for :\d\d
c: 0                                         ; time counter

parse input [                                ; parse the input (STDIN)
                                             ; (no regex in Rebol)

  any [                                      ; match zero or more... 
                                             ;
      copy x [a b b] (c: c + do x)           ;  HH:MM:SS or H:MM:SS
                                             ;    - copy match to x
                                             ;    - increment time (c) by x
                                             ; OR
    | copy x [a b] (c: c + do join "0:" x)   ;  MM:SS or M:SS
                                             ;    - copy match to x
                                             ;    - "MM:SS" into "0:MM:SS" (join)
                                             ;    - then increment time (c)
                                             ; OR
    | skip                                   ;   no match so move through input
  ]
]

print reword "$1h $2m $3s" [1 c/1 2 c/2 3 c/3]

Rebol viene fornito con il proprio time!tipo di dati. Puoi vedere come il codice sopra riportato lo utilizza dall'esempio seguente (dall'interno della console di Rebol):

>> 0:10:37 + 0:3:30 + 0:9:13 + 0:3:15 + 1:05:26
== 1:32:01

;; Rebol would treat 10:37 as 10 hours & 37 minutes (and not MM:SS)
;; So we have to prefix the "0:"

>> join "0:" 10:37
== "0:10:37"

;; This is a string so we use Rebol DO evaluator to convert to time!

>> do join "0:" 10:37 
== 0:10:37

>> type? do join "0:" 10:37
== time!

>> hms: do join "0:" 10:37
== 0:10:37

>> hms/hour
== 0

>> hms/second
== 37

>> hms/minute
== 10

2

Groovy - 195

M=60
r=(System.in.text=~/((\d?\d):)?(\d\d):(\d\d)/).collect{it[2..4]*.toInteger().inject{s,i->(s?:0)*M+i}}.inject{s,i->s+=i}
f=[];(2..0).each{j=M**it;s=r%j;f<<(r-s)/j;r=s}
printf("%sh %sm %ss",f)

Non riesco a capire come comprimerlo di più.

Ungolfed

M=60
r=(System.in.text=~/((\d?\d):)?(\d\d):(\d\d)/).collect{  // extract dates
    it[2..4]*.toInteger().inject{ s,i ->                 // convert to seconds
        (s?:0)*M+i
    }
}.inject{s,i ->
    s+=i                                                 // sum seconds
}

f=[];
(2..0).each{                                             // convert to h,m,s
    j=M**it;
    s=r%j;
    f<<(r-s)/j;
    r=s
}

printf("%sh %sm %ss",f)

1

Mathematica 300 caratteri

Questo piccolo esercizio ha richiesto molto codice, anche per Mathematica. Sicuramente ci sono modi più efficienti per farlo.

golfed

Supponendo che l'ingresso sia archiviato txt,

n=NumberString;
t=ToExpression;
o=TimeObject;

QuotientRemainder[QuantityMagnitude[Plus@@((o[#]-o[{0,0,0}])&/@
(StringSplit[StringCases[w,{(n~~":"~~n~~":"~~n),(n~~":"~~n)}],":"]
/.{{a_,b_}:> {0,t@a,t@b},{a_,b_,c_}:> {t@a,t@b,t@c}}))],60]/.{h_,m_}:> 
Row[{h,"h ",IntegerPart@m,"m ",Round[60 FractionalPart[m]],"s "}]

Come funziona (usando il codice unGolfed):

1-Trova i tempi.

StringCases[txt,{(NumberString~~":"~~NumberString~~":"~~NumberString),
(NumberString~~":"~~NumberString)}];

{"10:37", "3:30", "9:13", "03:15", "1:05:26"}


2-Break in ore, minuti, secondi

StringSplit[%,":"]/.{{a_,b_}:> {0,ToExpression@a,ToExpression@b},{a_,b_,c_}:> 
{ToExpression@a,ToExpression@b,ToExpression@c}}

{{0, 10, 37}, {0, 3, 30}, {0, 9, 13}, {0, 3, 15}, {1, 5, 26}}


Somma 3 volte i tempi. Gli oggetti tempo sono orari. Sottrarre un oggetto time da un altro restituisce una durata, in questo caso 92.0167 minuti. QuantityMagnitudelascia cadere l'unità di misura.

q=QuantityMagnitude[Plus@@((TimeObject[#]-TimeObject[{0,0,0}])&/@%)]

92,0167


4-Converti 92.0167 minuti in ore, minuti, secondi.

QuotientRemainder[q,60]/.{h_,m_}:> Row[{h,"h ",IntegerPart@m,"m ",
Round[60 FractionalPart[m]],"s "}]

1h 32m 1s


1

Perl, 146

La mia voce stampa l'output con uno spazio finale - spero sia ok

while(<>){for(/(\d?\d(?::\d\d){1,2})/g){$m=1;for(reverse split/:/,$_){$t+=$m*$_;$m*=60}}}for('s','m'){$o=($t%60)."$_ $o";$t/=60}print int$t,"h $o"

Se possiamo supporre che ci sarà una sola volta per riga di input, possiamo tagliare 4 caratteri:

while(<>){if(/(\d?\d(:\d\d){1,2})/){$m=1;for(reverse split/:/,$&){$t+=$m*$_;$m*=60}}}for('s','m'){$o=($t%60)."$_ $o";$t/=60}print int$t,"h $o"

Questi funzionano accumulando i secondi totali trascorsi e formattando quel valore in seguito.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.