Калькулятор рабочего времени

9

Это основано на том, как моя компания занимается мониторингом рабочего времени каждого сотрудника. У каждого из нас есть карточка, которую можно передать перед датчиком, чтобы часы регистрировали время, когда сотрудники регистрируются в офисе или выходят из него. Каждый раз, когда регистр связан с кодом:

  • Код 0: работник прибывает (или возвращается) в офис.
  • Код 1: работник покидает офис на обед.
  • Код 2: работник покидает офис в конце дня.
  • Код 3: работник уходит с работы по служебным причинам.
  • Код 4: работник покидает офис по личным причинам.

Регистры с кодом 0 иногда называют «нулевыми регистрами», а регистры с кодами с 1 по 4 иногда называют «ненулевыми регистрами».

Итак, обычный день для работника будет генерировать список регистров, как это:

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

Тем не менее, сотрудники иногда делают ошибки. Следующие ошибки автоматически исправляются системой:

  • Есть две последовательные ненулевые записи. Если первая ненулевая запись имеет код 4, автоматический регистр кода 0 добавляется через 15 минут или за 1 минуту до следующих регистров, если он был зарегистрирован менее чем через 15 минут после. Если первая ненулевая запись имеет код 3, автоматический регистр кода 0 всегда добавляется за 1 минуту до следующего регистра. Каждый другой случай выдает ошибку. Примеры:

    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.
    
  • Сотрудник зарегистрировал два регистра кода 1 или два регистра кода 2. Поскольку эти два на самом деле взаимозаменяемы, это не считается ошибкой. Если регистры с кодом 1 или кодом 2 имеют сумму более 2, это приводит к ошибке.

Соревнование

Основная задача - подсчитать, сколько часов и минут сотрудник провел в офисе. Это делается после исправления (если необходимо и возможно) списка входных регистров. Обратите внимание, что правильный список регистров будет чередовать нулевые регистры с ненулевыми регистрами.

Таким образом, алгоритм получит список регистров для сотрудника и заданного дня и вернет время, потраченное на работу в этот день. Если время не может рассчитать время, проведенное в случае ошибок, оно вернет 0 часов, 0 минут.

Правила:

  • Затраченное время представляет собой сумму времени, потраченного между каждым регистром кода 0 и следующим ненулевым регистром. Если ненулевой код равен 3, будет также учитываться время, проведенное между этим регистром и следующим регистром кода 0.
  • Можно предположить, что список входных регистров будет в порядке возрастания времени, и что все регистры будут с того же дня (никто не будет работать после полуночи).
  • Входной регистр не будет пустым.
  • Формат ввода может быть любым, в котором нуждается ваш код, если время выражается значением часа и значением минуты (число часов с плавающей запятой не будет допустимым вводом). Примеры: список с кодами и список со временем в виде строк, причем оба списка имеют одинаковую длину; список списков целых чисел, представляющих собой целые числа, код, часы и минуты регистров ...
  • Вывод может быть строкой со временем (в любом формате: H: mm, HH: mm, H: m ...); список из двух целых чисел с вычисленными часами и минутами; все, что может быть интерпретировано как кортеж часовых минут (число с плавающей запятой с затраченными часами не будет разрешено). Или вы можете распечатать результат в STDOUT.

Контрольные примеры

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

Я знаю, что это может сбивать с толку (в реальной проблеме нужно было рассмотреть еще больше случаев, поэтому я это знаю). Пожалуйста, не стесняйтесь спрашивать больше примеров.

Это и пусть победит самый короткий код для каждого языка!


Вы можете прокомментировать, как улучшить систему, если хотите, но это не главное. Мой босс не склонен тратить время на его изменение. :-)

Чарли
источник
Песочница .
Чарли

Ответы:

3

Python 3 , 327 322 318 317 байт

Спасибо за @JonathanFrech и @ Mr.Xcoder за избавление от некоторых байтов.

Вводит в виде списка кодов ( C) и списка времен ( T) ( (hours, minutes)кортежей). Возвращает (hours, minutes)кортеж

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)

Проверено на приведенных примерах.

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)
Ханнес Карппила
источник
318 байт .
Джонатан Фрех
Это отрицание, о котором я не думал. Хорошие трюки.
Ханнес Карппила
Вы можете использовать L(3)вместо 3in C.
г-н Xcoder