Le calculateur de temps de travail

9

Ceci est basé sur la façon dont mon entreprise gère le suivi des temps de travail pour chaque employé. Chacun de nous a une carte qui peut être passée devant un capteur, de sorte qu'une horloge enregistre les heures auxquelles les employés arrivent ou sortent du bureau. Chaque fois que le registre est lié à un code:

  • Code 0: l'employé arrive (ou revient) au bureau.
  • Code 1: l'employé quitte le bureau pour le déjeuner.
  • Code 2: l'employé quitte le bureau en fin de journée.
  • Code 3: l'employé quitte le bureau pour des raisons professionnelles.
  • Code 4: l'employé quitte le bureau pour des raisons personnelles.

Les registres du code 0 seront parfois appelés «registres zéro» et les registres du code 1 au code 4 seront parfois appelés «registres non nuls».

Ainsi, une journée normale pour un travailleur générerait une liste de registres comme celle-ci:

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

Néanmoins, les employés font parfois des erreurs. Les erreurs suivantes sont automatiquement corrigées par le système:

  • Il existe deux enregistrements non nuls consécutifs. Si le premier enregistrement non nul a un code 4, un registre automatique de code 0 est ajouté 15 minutes après, ou 1 minute avant les prochains registres s'il a été enregistré moins de 15 minutes après. Si le premier enregistrement non nul a un code 3, un registre automatique de code 0 est toujours ajouté 1 minute avant le prochain registre. Tous les autres cas produisent une erreur. Exemples:

    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.
    
  • L'employé a enregistré deux registres de code 1 ou deux registres de code 2. Comme ces deux sont en fait interchangeables, cela ne compte pas comme une erreur. Si les registres de code 1 ou de code 2 totalisent plus de 2 registres, cela génère une erreur.

Le défi

L'objectif principal est de calculer combien d'heures et de minutes l'employé a passé au bureau. Cela se fait après avoir fixé (si nécessaire et possible) la liste des registres d'entrée. Notez qu'une liste de registres appropriée alternera les registres nuls avec des registres non nuls.

Ainsi, l'algorithme recevra la liste des registres pour un employé et un jour donné, et renverra le temps passé à travailler pour ce jour. Si le temps ne peut pas calculer le temps passé en cas d'erreur, il retournera 0 heures, 0 minutes.

Règles:

  • Le temps passé est la somme du temps passé entre chaque registre de code 0 et le registre non nul suivant. Si le code non nul est un 3, le temps passé entre ce registre et le registre de code 0 suivant sera également compté.
  • Vous pouvez supposer que la liste des registres d'entrée sera dans l'ordre chronologique croissant et que tous les registres proviendront du même jour (personne ne fonctionnera après minuit).
  • Le registre d'entrée ne sera pas vide.
  • Le format d'entrée peut être tout ce dont votre code a besoin, tant que l'heure est exprimée avec la valeur heure et la valeur minute (un nombre d'heures à virgule flottante ne sera pas une entrée valide). Exemples: Une liste avec les codes et une liste avec le temps sous forme de chaînes, les deux listes ayant la même longueur; une liste de listes d'entiers, étant les entiers le code, l'heure et les minutes des registres ...
  • La sortie peut être une chaîne avec l'heure (dans n'importe quel format souhaité: H: mm, HH: mm, H: m ...); une liste de deux entiers avec les heures et les minutes calculées; tout ce qui peut être interprété comme un tuple heure-minute (un nombre à virgule flottante avec les heures passées ne sera pas autorisé). Ou vous pouvez imprimer le résultat sur STDOUT.

Cas de 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

Je sais que cela peut être déroutant (le problème du monde réel avait encore plus de cas à considérer, donc je le sais). N'hésitez pas à demander plus d'exemples.

C'est le , donc le code le plus court pour chaque langue peut gagner!


Vous pouvez commenter comment améliorer le système si vous le souhaitez, mais ce n'est pas le but. Mon patron n'est pas enclin à passer du temps à le changer. :-)

Charlie
la source
Sandbox .
Charlie

Réponses:

3

Python 3 , 327 322 318 317 octets

Merci pour @JonathanFrech et @ Mr.Xcoder de se débarrasser de certains octets.

Prend la saisie sous forme de liste de codes ( C) et de liste de temps ( T) ( (hours, minutes)tuples). Renvoie un (hours, minutes)tuple.

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)

Vérifié par rapport aux exemples donnés.

Non golfé

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
la source
318 octets .
Jonathan Frech
Cette négation à laquelle je n'ai pas pensé. Belles astuces.
Hannes Karppila
vous pouvez utiliser à la L(3)place de 3in C.
M. Xcoder