労働時間計算機


9

これは、私の会社がすべての従業員の労働時間の監視をどのように扱っているかに基づいています。一人一人がセンサーの前を通過できるカードを持っているので、時計は従業員がオフィスにチェックインまたはチェックアウトする時刻を記録します。レジスターがコードにリンクされるたびに:

  • コード0:従業員がオフィスに到着する(またはオフィスに戻る)。
  • コード1:従業員は昼食のためにオフィスを離れます。
  • コード2:従業員は1日の終わりにオフィスを離れます。
  • コード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

それにもかかわらず、従業員は時々間違いを犯します。次のエラーはシステムによって自動的に修正されます。

  • 2つの連続したゼロ以外のレコードがあります。最初のゼロ以外のレコードにコード4がある場合、自動コード0レジスタが15分後に追加されます。15分未満で登録されている場合は、次のレジスタの1分前に追加されます。最初のゼロ以外のレコードにコード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.
    
  • 従業員は2つのコード1レジスタまたは2つのコード2レジスタを登録しました。これら2つは実際には互換性があるため、エラーとしてカウントされません。コード1またはコード2のレジスタの合計が2つを超えると、エラーが発生します。

チャレンジ

主な目的は、従業員がオフィスで過ごした時間と分を計算することです。これは、(必要に応じて可能であれば)入力レジスタリストを修正した後に行われます。適切なレジスタリストは、ゼロレジスタを非ゼロレジスタで代替することに注意してください。

そのため、アルゴリズムは従業員のレジスターのリストと特定の日を受け取り、その日の作業に費やされた時間を返します。エラー発生時に費やした時間を計算できない場合は、0時間0分が返されます。

ルール:

  • 費やされた時間は、すべてのコード0レジスタとそれに続くゼロ以外のレジスタとの間で費やされた時間の合計です。ゼロ以外のコードが3の場合、そのレジスターとそれに続くコード0レジスターの間で費やされた時間もカウントされます。
  • 入力レジスタリストは昇順の時間順になり、すべてのレジスタは同じ日からのものであると想定できます(真夜中を超えて作業することはありません)。
  • 入力レジスタは空になりません。
  • 時間を時間値と分値で表現する限り、入力形式はコードで必要なものにすることができます(浮動小数点数の時間は有効な入力ではありません)。例:コードを含むリストと時間を文字列として含むリスト。どちらのリストも同じ長さです。整数のリストのリスト、レジスターのコード、時間、分である整数...
  • 出力は、時間を含む文字列にすることができます(任意の形式:H:mm、HH:mm、H:m ...); 時間と分が計算された2つの整数のリスト。1時間分のタプルとして解釈できるもの(費やした時間を含む浮動小数点数は許可されません)。または、結果を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の3327の 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年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.