Il calcolatore dell'orario di lavoro


9

Questo si basa sul modo in cui la mia azienda si occupa del monitoraggio dell'orario di lavoro di ogni dipendente. Ognuno di noi ha una carta che può essere passata davanti a un sensore, in modo che un orologio registri i tempi in cui i dipendenti effettuano il check-in o out dall'ufficio. Ogni volta che il registro è collegato a un codice:

  • Codice 0: il dipendente arriva (o ritorna) in ufficio.
  • Codice 1: l'impiegato lascia l'ufficio per pranzo.
  • Codice 2: l'impiegato lascia l'ufficio alla fine della giornata.
  • Codice 3: il dipendente lascia l'ufficio per motivi di lavoro.
  • Codice 4: il dipendente lascia l'ufficio per motivi personali.

I registri di codice 0 vengono talvolta definiti "registri zero", mentre i registri da codice 1 a codice 4 vengono talvolta definiti "registri diversi da zero".

Quindi, un giorno normale per un lavoratore genererebbe un elenco di registri come questo:

Code/Time
------------
0   8:17  // The employee arrives at the office
4  11:34  // The employee leaves the office to smoke
0  11:41  // The employee returns to the office
1  13:37  // The employee leaves the office to have lunch
0  14:11  // The employee returns to the office
3  15:02  // The employee leaves the office to visit a client
0  16:48  // The employee returns to the office
2  17:29  // The employee leaves the office to go home

Tuttavia, i dipendenti a volte commettono errori. I seguenti errori vengono automaticamente corretti dal sistema:

  • Esistono due record consecutivi diversi da zero. Se il primo record diverso da zero ha un codice 4, viene aggiunto un registro codice 0 automatico 15 minuti dopo o 1 minuto prima dei registri successivi se è stato registrato meno di 15 minuti dopo. Se il primo record diverso da zero ha un codice 3, un registro codice 0 automatico viene sempre aggiunto 1 minuto prima del registro successivo. Ogni altro caso produce un errore. Esempi:

    Code/Time
    ------------
    0   8:17  // The employee arrives at the office
    4  11:34  // The employee leaves the office to smoke
    1  13:37  // The employee leaves the office to have lunch
    // Automatic register with code 0 added at 11:49.
    
    Code/Time
    ------------
    0   8:17  // The employee arrives at the office
    4  11:34  // The employee leaves the office to smoke
    4  11:39  // The employee leaves again the office for personal reasons
    // Automatic register with code 0 added at 11:38.
    
    Code/Time
    ------------
    0   8:17  // The employee arrives at the office
    3  11:34  // The employee leaves the office to visit a client
    1  14:09  // The employee leaves the office to have lunch
    // Automatic register with code 0 added at 14:08.
    
  • Il dipendente ha registrato due registri codice 1 o due registri codice 2. Poiché questi due sono in effetti intercambiabili, ciò non viene considerato un errore. Se i registri del codice 1 o del codice 2 sommano più di 2 registri, viene generato un errore.

La sfida

L'obiettivo principale è calcolare quante ore e minuti il ​​dipendente ha trascorso in ufficio. Ciò avviene dopo aver corretto (se necessario e possibile) l'elenco dei registri di input. Si noti che un elenco di registri adeguato alternerà registri zero con registri diversi da zero.

Quindi, l'algoritmo riceverà l'elenco dei registri per un dipendente e un giorno dedicato e restituirà il tempo impiegato a lavorare per quel giorno. Se il tempo non è in grado di calcolare il tempo trascorso in caso di errori, verrà restituito 0 ore, 0 minuti.

Regole:

  • Il tempo impiegato è la somma del tempo trascorso tra ogni registro codice 0 e il seguente registro diverso da zero. Se il codice diverso da zero è un 3, verrà conteggiato anche il tempo trascorso tra quel registro e il seguente registro codice 0.
  • Si può presumere che l'elenco dei registri di input sia in ordine temporale crescente e che tutti i registri saranno dello stesso giorno (nessuno lavorerà oltre la mezzanotte).
  • Il registro di input non sarà vuoto.
  • Il formato di input può essere tutto ciò di cui il tuo codice ha bisogno, purché l'ora sia espressa con il valore dell'ora e il valore dei minuti (un numero in virgola mobile di ore non sarà un input valido). Esempi: un elenco con i codici e un elenco con l'ora come stringhe, entrambe le liste hanno la stessa lunghezza; un elenco di liste di numeri interi, che sono numeri interi il codice, l'ora e i minuti dei registri ...
  • L'output può essere una stringa con il tempo (in qualsiasi formato desiderato: H: mm, HH: mm, H: m ...); un elenco di due numeri interi con le ore e i minuti calcolati; tutto ciò che può essere interpretato come una tupla ora-minuto (un numero in virgola mobile con le ore trascorse non sarà consentito). Oppure puoi stampare il risultato su STDOUT.

Casi test

Code/Time
------------
0   8:17  // Check in
4  11:34  // Check out. Time spent since check in:  3:17
0  11:41  // Check in
1  13:37  // Check out. Time spent since check in:  1:56
0  14:11  // Check in
3  15:02  // Check out. Time spent since check in:  0:51
0  16:48  // Check in.  Time spent working outside: 1:46
2  17:29  // Check out. Time spent since check in:  0:41
// Total time (value returned): 8:31

Code/Time
------------
0   8:17
4  11:34  // Time spent: 3:17
1  15:52  // Time spent since 11:49 (automatic register 15 minutes after
          // a code 4 register): 4:03
// Total time: 7:20

Code/Time
------------
0   8:17
4  15:47  // Time spent: 7:30
1  15:52  // Time spent since 15:51 (automatic register after a code 4
          // register 1 minute before the next register as it is too
          // close in time): 0:01
// Total time: 7:31

Code/Time
------------
0   8:17
1  13:34  // Time spent: 5:17
0  14:04
1  17:55  // Time spent: 3:51 (last code 1 should be a code 2 but it does not matter)
// Total time: 9:08

Code/Time
------------
0   8:17
1  13:34
0  14:04
1  17:05
0  17:08
2  17:44
// Total time: 0:00 (too many code 1 and code 2 registers)

Code/Time
------------
0   8:17
1  13:34  // A code 1 register does not generate an automatic code 0 register
2  17:41
// Total time: 0:00 (there's a code 0 register missing)

Code/Time
------------
0   8:17
0  13:34  // what happened between these two check in registers?
2  17:41
// Total time: 0:00 (there's a check out register missing)

Code/Time
------------
0   8:17
0  13:37  // This should probably be a code 1 register, but we cannot be sure
0  14:11
2  17:29
// Total time: 0:00

So che questo può essere fonte di confusione (il problema del mondo reale aveva ancora più casi da considerare, quindi lo so). Per favore, non esitate a chiedere altri esempi.

Questo è , quindi può vincere il codice più breve per ogni lingua!


Puoi commentare come migliorare il sistema se vuoi, ma non è questo il punto. Il mio capo non è incline a passare il tempo a cambiarlo. :-)


Risposte:


3

Python 3 , 327 322 318 317 byte

Grazie per @JonathanFrech e @ Mr.Xcoder per aver eliminato alcuni byte.

Accetta input come elenco di codici ( C) e elenco di orari ( T) ( (hours, minutes)tuple). Restituisce una (hours, minutes)tupla.

def f(C,T):
 T,L=[m+h*60for h,m in T],C.count
 for z in range(len(C))[::-1]:
  c=C[~-z]
  if c*C[z]:
   if c<3:return 0,0
   C.insert(z,0);b=~-T[z];T.insert(z,b if c-4else min(T[~-z]+15,b))
 while L(3):i=C.index(3);del C[i:i+2],T[i:i+2]
 return(0,0)if L(1)+L(2)>2or 0in C[1::2]else divmod(sum(T[1::2])-sum(T[::2]),60)

Verificato contro esempi forniti.

Ungolfed

def f(C, T):
    # use minutes since midnight instead of (hours, minutes)
    T=[m+h*60 for h,m in T]

    # error correction
    for z in range(len(C))[::-1]:
        if C[z-1] and C[z]:
            if C[z-1]<3:
                return 0,0

            C.insert(z,0)
            b=T[z]-1
            T.insert(z, b if C[z-1] != 4 else min(T[z-1]+15, b))

    # simplification (remove work trips (code 3))
    while L(3): # 3 in C
        i=C.index(3)
        del C[i:i+2]
        del T[i:i+2]

    # error check
    if 0 in C[1::2] or 2 < C.count(1) + C.count(2):
        return 0,0

    # sum
    s = sum(T[1::2])-sum(T[::2])

    # to (hours, minutes)
    return divmod(s, 60)


Quella negazione a cui non ho pensato. Bei trucchi.
Hannes Karppila, il

puoi usare al L(3)posto di 3in C.
Mr. Xcoder
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.