Der Arbeitszeitrechner

9

Dies basiert darauf, wie mein Unternehmen mit der Überwachung der Arbeitszeiten für jeden Mitarbeiter umgeht. Jeder von uns hat eine Karte, die vor einem Sensor ausgegeben werden kann, sodass eine Uhr die Zeiten registriert, zu denen die Mitarbeiter im Büro ein- oder auschecken. Jedes Mal, wenn das Register mit einem Code verknüpft ist:

  • Code 0: Der Mitarbeiter kommt im Büro an (oder kehrt zum Büro zurück).
  • Code 1: Der Mitarbeiter verlässt das Büro zum Mittagessen.
  • Code 2: Der Mitarbeiter verlässt das Büro am Ende des Tages.
  • Code 3: Der Mitarbeiter verlässt das Büro aus beruflichen Gründen.
  • Code 4: Der Mitarbeiter verlässt das Büro aus persönlichen Gründen.

Code 0-Register werden manchmal als "Nullregister" bezeichnet, und Code 1 bis Code 4-Register werden manchmal als "Nicht-Null-Register" bezeichnet.

Ein normaler Tag für einen Arbeiter würde also eine Registerliste wie die folgende generieren:

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

Trotzdem machen die Mitarbeiter manchmal Fehler. Die folgenden Fehler werden vom System automatisch behoben:

  • Es gibt zwei aufeinanderfolgende Datensätze ungleich Null. Wenn der erste Datensatz ungleich Null einen Code 4 hat, wird ein automatisches Code-0-Register 15 Minuten später oder 1 Minute vor dem nächsten Register hinzugefügt, wenn es weniger als 15 Minuten später registriert wurde. Wenn der erste Datensatz ungleich Null einen Code 3 hat, wird ein automatisches Code 0-Register immer 1 Minute vor dem nächsten Register hinzugefügt. Jeder andere Fall erzeugt einen Fehler. Beispiele:

    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.
    
  • Der Mitarbeiter hat zwei Code-1-Register oder zwei Code-2-Register registriert. Da diese beiden tatsächlich austauschbar sind, zählt dies nicht als Fehler. Wenn die Register Code 1 oder Code 2 mehr als 2 Register summieren, führt dies zu einem Fehler.

Die Herausforderung

Das Hauptziel besteht darin, zu berechnen, wie viele Stunden und Minuten der Mitarbeiter im Büro verbracht hat. Dies erfolgt nach dem Fixieren (falls erforderlich und möglich) der Eingangsregisterliste. Beachten Sie, dass eine ordnungsgemäße Registerliste Nullregister mit Nicht-Nullregistern abwechselt.

Der Algorithmus erhält also die Liste der Register für einen Mitarbeiter und einen bestimmten Tag und gibt die für diesen Tag aufgewendete Arbeitszeit zurück. Wenn die Zeit die im Fehlerfall aufgewendete Zeit nicht berechnen kann, werden 0 Stunden und 0 Minuten zurückgegeben.

Regeln:

  • Die aufgewendete Zeit ist die Summe der Zeit, die zwischen jedem Code 0-Register und dem folgenden Nicht-Null-Register verbracht wird. Wenn der Nicht-Null-Code eine 3 ist, wird auch die Zeit zwischen diesem Register und dem folgenden Code-0-Register gezählt.
  • Sie können davon ausgehen, dass die Eingaberegisterliste in aufsteigender Zeitreihenfolge angezeigt wird und dass alle Register vom selben Tag stammen (niemand wird nach Mitternacht arbeiten).
  • Das Eingangsregister wird nicht leer sein.
  • Das Eingabeformat kann alles sein, was Ihr Code benötigt, solange die Zeit mit dem Stundenwert und dem Minutenwert ausgedrückt wird (eine Gleitkommazahl von Stunden ist keine gültige Eingabe). Beispiele: Eine Liste mit den Codes und eine Liste mit der Zeit als Zeichenfolgen, wobei beide Listen dieselbe Länge haben; eine Liste von Ganzzahllisten, wobei die Ganzzahlen der Code, die Stunde und die Minuten der Register sind ...
  • Die Ausgabe kann eine Zeichenfolge mit der Zeit sein (in jedem gewünschten Format: H: mm, HH: mm, H: m ...); eine Liste von zwei ganzen Zahlen mit den berechneten Stunden und Minuten; Alles, was als Stunden-Minuten-Tupel interpretiert werden kann (eine Gleitkommazahl mit den aufgewendeten Stunden ist nicht zulässig). Oder Sie können das Ergebnis in STDOUT drucken.

Testfälle

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

Ich weiß, dass dies verwirrend sein kann (das Problem der realen Welt hatte noch mehr Fälle zu berücksichtigen, also weiß ich das). Bitte zögern Sie nicht, weitere Beispiele anzufordern.

Dies ist , also kann der kürzeste Code für jede Sprache gewinnen!


Sie können kommentieren, wie Sie das System verbessern können, wenn Sie möchten, aber das ist nicht der Punkt. Mein Chef ist nicht geneigt, Zeit damit zu verbringen, es zu ändern. :-)

Charlie
quelle
Sandkasten .
Charlie

Antworten:

3

Python 3 , 327 322 318 317 Bytes

Vielen Dank für @JonathanFrech und @ Mr.Xcoder, dass Sie einige Bytes entfernt haben.

Übernimmt die Eingabe als Liste der Codes ( C) und Liste der Zeiten ( T) ( (hours, minutes)Tupel). Gibt ein (hours, minutes)Tupel zurück.

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)

Verifiziert gegen gegebene Beispiele.

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)
Hannes Karppila
quelle
318 Bytes .
Jonathan Frech
An diese Negation habe ich nicht gedacht. Schöne Tricks.
Hannes Karppila
Sie können L(3)anstelle von verwenden 3in C.
Herr Xcoder