Kalkulator czasu pracy

9

Jest to oparte na tym, jak moja firma zajmuje się monitorowaniem czasu pracy każdego pracownika. Każdy z nas ma kartę, którą można przekazać przed czujnikiem, dzięki czemu zegar rejestruje godziny, w których pracownicy meldują się lub wychodzą z biura. Za każdym razem, gdy rejestr jest powiązany z kodem:

  • Kod 0: pracownik przybywa do biura lub wraca do niego.
  • Kod 1: pracownik opuszcza biuro na lunch.
  • Kod 2: pracownik opuszcza biuro pod koniec dnia.
  • Kod 3: pracownik opuszcza biuro z przyczyn związanych z pracą.
  • Kod 4: pracownik opuszcza biuro z powodów osobistych.

Rejestry kodu 0 będą czasami nazywane „rejestrami zerowymi”, a kody 1 do rejestrów kodu 4 będą czasami nazywane „rejestrami niezerowymi”.

Tak więc normalny dzień dla pracownika generowałby listę rejestrów w następujący sposób:

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

Niemniej jednak pracownicy czasami popełniają błędy. System automatycznie naprawia następujące błędy:

  • Istnieją dwa kolejne niezerowe rekordy. Jeśli pierwszy niezerowy rekord ma kod 4, automatyczny rejestr kodu 0 jest dodawany 15 minut później lub 1 minutę przed kolejnymi rejestrami, jeśli został zarejestrowany mniej niż 15 minut później. Jeśli pierwszy niezerowy rekord ma kod 3, automatyczny rejestr kodu 0 jest zawsze dodawany 1 minutę przed następnym rejestrem. Co drugi przypadek powoduje błąd. Przykłady:

    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.
    
  • Pracownik zarejestrował dwa rejestry kodu 1 lub dwa rejestry kodu 2. Ponieważ te dwa są w rzeczywistości wymienne, nie jest to traktowane jako błąd. Jeśli rejestry kodu 1 lub kodu 2 sumują więcej niż 2 rejestry, powoduje to błąd.

Wyzwanie

Głównym celem jest obliczenie liczby godzin i minut, które pracownik spędził w biurze. Odbywa się to po ustaleniu (jeśli jest to konieczne i możliwe) listy rejestrów wejściowych. Zauważ, że właściwa lista rejestrów będzie zamieniała rejestry zerowe na rejestry niezerowe.

Algorytm otrzyma więc listę rejestrów pracownika i poda dzień, a także zwróci czas poświęcony na pracę tego dnia. Jeśli czas nie może obliczyć czasu spędzonego w przypadku błędów, zwróci 0 godzin, 0 minut.

Zasady:

  • Czas spędzony jest sumą czasu spędzonego między każdym rejestrem o kodzie 0 a kolejnym rejestrem niezerowym. Jeśli niezerowy kod to 3, czas między tym rejestrem a następującym rejestrem kodu 0 również zostanie zliczony.
  • Możesz założyć, że lista rejestrów wejściowych będzie w porządku rosnącym i że wszystkie rejestry będą tego samego dnia (nikt nie będzie pracował po północy).
  • Rejestr wejściowy nie będzie pusty.
  • Format wejściowy może być wszystkim, czego potrzebuje Twój kod, pod warunkiem, że czas jest wyrażony wartością godziny i wartością minuty (liczba zmiennoprzecinkowa godzin nie będzie poprawnym wejściem). Przykłady: lista z kodami i lista z czasem jako ciągami znaków, przy czym obie listy mają tę samą długość; lista list liczb całkowitych, będących liczbami całkowitymi kod, godzina i minuty rejestrów ...
  • Dane wyjściowe mogą być ciągiem z czasem (w dowolnym formacie: H: mm, HH: mm, H: m ...); lista dwóch liczb całkowitych z obliczonymi godzinami i minutami; wszystko, co można interpretować jako krotkę minuta-minuta (liczba zmiennoprzecinkowa z spędzonymi godzinami nie będzie dozwolona). Lub możesz wydrukować wynik do STDOUT.

Przypadki testowe

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

Wiem, że może to być mylące (problem w rzeczywistości miał jeszcze więcej spraw do rozważenia, więc wiem o tym). Nie wahaj się prosić o więcej przykładów.

To jest , aby wygrał najkrótszy kod dla każdego języka!


Możesz skomentować, jak ulepszyć system, jeśli chcesz, ale nie o to chodzi. Mój szef nie ma skłonności do spędzania czasu na zmienianiu go. :-)

Charlie
źródło
Piaskownica .
Charlie,

Odpowiedzi:

3

Python 3 , 327 322 318 317 bajtów

Dzięki za @JonathanFrech i @ Mr.Xcoder za pozbycie się niektórych bajtów.

Pobiera dane wejściowe jako listę kodów ( C) i listę czasów ( T) ( (hours, minutes)krotek). Zwraca (hours, minutes)krotkę.

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)

Zweryfikowano na podstawie podanych przykładów.

Nie golfił

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)
Hannes Karppila
źródło
318 bajtów .
Jonathan Frech,
Negacji, o której nie myślałem. Niezłe sztuczki.
Hannes Karppila,
możesz użyć L(3)zamiast3in C .
Pan Xcoder,