A calculadora do tempo de trabalho

9

Isso se baseia em como minha empresa lida com o monitoramento dos horários de trabalho de todos os funcionários. Cada um de nós tem um cartão que pode ser passado na frente de um sensor, para que um relógio registre as horas em que os funcionários fazem check-in ou check-out no escritório. Toda vez que o registro é vinculado a um código:

  • Código 0: o funcionário chega (ou retorna) ao escritório.
  • Código 1: o funcionário sai do escritório para almoçar.
  • Código 2: o funcionário sai do escritório no final do dia.
  • Código 3: o funcionário sai do escritório por motivos de trabalho.
  • Código 4: o funcionário sai do escritório por motivos pessoais.

Às vezes, os registros do código 0 são chamados de "registros zero" e o código 1 para os registros do código 4 às vezes é chamado "registros diferentes de zero".

Portanto, um dia normal para um trabalhador geraria uma lista de registros 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 entanto, os funcionários às vezes cometem erros. Os seguintes erros são corrigidos automaticamente pelo sistema:

  • Existem dois registros consecutivos diferentes de zero. Se o primeiro registro diferente de zero tiver um código 4, um registro automático de código 0 será adicionado 15 minutos depois ou 1 minuto antes do próximo registro, se tiver sido registrado menos de 15 minutos depois. Se o primeiro registro diferente de zero tiver um código 3, um registro automático de código 0 será sempre adicionado 1 minuto antes do próximo registro. Todos os outros casos produzem um erro. Exemplos:

    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.
    
  • O funcionário registrou dois registros de código 1 ou dois de código 2. Como esses dois são de fato intercambiáveis, isso não conta como um erro. Se os registros de código 1 ou 2 somarem mais de 2 registros, isso produzirá um erro.

O desafio

O objetivo principal é calcular quantas horas e minutos o funcionário passou no escritório. Isso é feito após a correção (se necessário e possível) da lista de registros de entrada. Observe que uma lista de registros adequada alternará zero registros com registros diferentes de zero.

Portanto, o algoritmo receberá a lista de registros de um funcionário e um dia útil e retornará o tempo gasto trabalhando para esse dia. Se o tempo não puder calcular o tempo gasto em caso de erros, ele retornará 0 horas, 0 minutos.

Regras:

  • O tempo gasto é a soma do tempo gasto entre cada registro de código 0 e o seguinte registro diferente de zero. Se o código diferente de zero for um 3, o tempo gasto entre esse registro e o seguinte código 0 também será contado.
  • Você pode assumir que a lista de registradores de entrada estará em ordem crescente de tempo e que todos os registradores serão do mesmo dia (ninguém trabalhará além da meia-noite).
  • O registro de entrada não estará vazio.
  • O formato de entrada pode ser qualquer coisa que seu código precise, desde que a hora seja expressa com o valor da hora e o valor do minuto (um número de horas de ponto flutuante não será uma entrada válida). Exemplos: Uma lista com os códigos e uma lista com o tempo como seqüências de caracteres, ambas as listas com o mesmo comprimento; uma lista de listas de números inteiros, sendo os inteiros o código, a hora e os minutos dos registros ...
  • A saída pode ser uma sequência com a hora (em qualquer formato que você desejar: H: mm, HH: mm, H: m ...); uma lista de dois números inteiros com as horas e minutos calculados; qualquer coisa que possa ser interpretada como uma tupla de hora e minuto (um número de ponto flutuante com as horas gastas não será permitido). Ou você pode imprimir o resultado em STDOUT.

Casos de teste

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

Eu sei que isso pode ser confuso (o problema do mundo real tinha ainda mais casos a considerar, então eu sei disso). Por favor, não hesite em pedir mais exemplos.

Este é o , portanto, pode ganhar o código mais curto para cada idioma!


Você pode comentar como melhorar o sistema, se quiser, mas esse não é o ponto. Meu chefe não é propenso a gastar tempo mudando isso. :-)

Charlie
fonte
Sandbox .
14147 Charlie

Respostas:

3

Python 3 , 327 322 318 317 bytes

Obrigado por @ JonathanFrech e @ Mr.Xcoder por se livrar de alguns bytes.

Recebe a entrada como lista de códigos ( C) e lista de tempos ( T) ( (hours, minutes)tuplas). Retorna uma (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 exemplos.

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
fonte
318 bytes .
22817 Jonathan Frech
Aquela negação em que não pensei. Truques agradáveis.
Hannes Karppila
você pode usar em L(3)vez de 3in C.
Mr. Xcoder