工作时间计算器


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分钟后添加;如果下一个寄存器的注册时间少于15分钟,则在下一个寄存器之前添加1分钟。如果第一个非零记录的代码为3,则始终在下一个寄存器之前1分钟添加自动代码0寄存器。其他所有情况都会产生错误。例子:

    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

我知道这可能会造成混淆(现实问题需要考虑更多案例,所以我知道这一点)。请不要犹豫,要求更多示例。

这是 ,因此每种语言的最短代码可能会获胜!


您可以根据需要评论如何改进系统,但这不是重点。我的老板不愿意花时间更改它。:-)


沙盒
查理

Answers:


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)

根据给定的示例进行了验证。

不打高尔夫球

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

您可以使用L(3)代替3in C
Xcoder先生18年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.