La calculadora de tiempo de trabajo

9

Esto se basa en cómo mi empresa se ocupa del monitoreo de los tiempos de trabajo de cada empleado. Cada uno de nosotros tiene una tarjeta que se puede pasar frente a un sensor, de modo que un reloj registra las horas en que los empleados ingresan o salen de la oficina. Cada vez que el registro está vinculado a un código:

  • Código 0: el empleado llega (o regresa) a la oficina.
  • Código 1: el empleado sale de la oficina para almorzar.
  • Código 2: el empleado abandona la oficina al final del día.
  • Código 3: el empleado abandona la oficina por motivos laborales.
  • Código 4: el empleado abandona la oficina por razones personales.

Los registros del código 0 a veces se denominarán "registros cero", y los registros del código 1 al código 4 a veces se denominarán "registros distintos de cero".

Entonces, un día normal para un trabajador generaría una lista de registro como esta:

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

No obstante, los empleados a veces cometen errores. El sistema corrige automáticamente los siguientes errores:

  • Hay dos registros consecutivos distintos de cero. Si el primer registro distinto de cero tiene un código 4, se agrega un registro automático de código 0 15 minutos después, o 1 minuto antes de los siguientes registros si se ha registrado menos de 15 minutos después. Si el primer registro distinto de cero tiene un código 3, siempre se agrega un registro automático de código 0 1 minuto antes del siguiente registro. Cualquier otro caso produce un error. Ejemplos:

    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.
    
  • El empleado registró dos registros de código 1 o dos registros de código 2. Como estos dos son de hecho intercambiables, eso no cuenta como un error. Si los registros de código 1 o código 2 suman más de 2 registros, eso produce un error.

El reto

El objetivo principal es calcular cuántas horas y minutos ha pasado el empleado en la oficina. Esto se hace después de arreglar (si es necesario y posible) la lista de registros de entrada. Tenga en cuenta que una lista de registros adecuada alternará registros cero con registros distintos de cero.

Por lo tanto, el algoritmo recibirá la lista de registros para un empleado y un día de entrega, y devolverá el tiempo dedicado a trabajar ese día. Si el tiempo no puede calcular el tiempo empleado en caso de errores, devolverá 0 horas, 0 minutos.

Reglas:

  • El tiempo dedicado es la suma del tiempo transcurrido entre cada registro de código 0 y el siguiente registro distinto de cero. Si el código distinto de cero es un 3, también se contará el tiempo transcurrido entre ese registro y el siguiente registro de código 0.
  • Puede suponer que la lista de registros de entrada estará en orden de tiempo ascendente y que todos los registros serán del mismo día (nadie trabajará más allá de la medianoche).
  • El registro de entrada no estará vacío.
  • El formato de entrada puede ser cualquier cosa que necesite su código, siempre que el tiempo se exprese con el valor de la hora y el valor de los minutos (un número de horas de coma flotante no será una entrada válida). Ejemplos: una lista con los códigos y una lista con el tiempo como cadenas, ambas listas tienen la misma longitud; una lista de listas de enteros, siendo los enteros el código, la hora y los minutos de los registros ...
  • La salida puede ser una cadena con el tiempo (en cualquier formato que desee: H: mm, HH: mm, H: m ...); una lista de dos enteros con las horas y minutos calculados; cualquier cosa que pueda interpretarse como una tupla de hora-minuto (no se permitirá un número de coma flotante con las horas dedicadas). O puede imprimir el resultado en STDOUT.

Casos de prueba

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

Sé que esto puede ser confuso (el problema del mundo real tenía aún más casos para considerar, así que lo sé). Por favor, no dude en pedir más ejemplos.

Este es el , ¡así que puede ganar el código más corto para cada idioma!


Puede comentar cómo mejorar el sistema si lo desea, pero ese no es el punto. Mi jefe no es propenso a pasar tiempo cambiándolo. :-)

Charlie
fuente
Caja de arena .
Charlie

Respuestas:

3

Python 3 , 327 322 318 317 bytes

Gracias por @JonathanFrech y @ Mr.Xcoder por deshacerse de algunos bytes.

Toma entrada como lista de códigos ( C) y lista de veces ( T) ( (hours, minutes)tuplas). Devuelve 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)

Verificado contra ejemplos dados.

Sin 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
fuente
318 bytes .
Jonathan Frech
Esa negación en la que no pensé. Buenos trucos.
Hannes Karppila
puedes usar en L(3)lugar de 3in C.
Sr. Xcoder