0. どんな問題?(問題の概要)
hh:mm 形式で与えられる $N$ 日分の入室時刻と退室時刻のリストから、合計滞在時間(H時間 M分)を求める問題です。
※特定の問題設定を抽象化し、「時刻文字列の計算処理」として整理しています。
1. 最初のアプローチとつまずいたポイント
入退室時刻から滞在時間を出すため、まずは replace(":", " ") で文字列を分割して数値化し、「分」に変換して引き算する方針で実装しました。
def to_minutes(a, b):
return 60 * a + b
#時間をすべて分数に直す関数
N = int(input())
matrix = [list(map(int, input().replace(":", " ").split())) for _ in range(N)]
#まず空白とか時間を表すためのコロンをとったバラバラの値を2次元配列に入れる
sum = 0
#読み返すと、sumは標準関数名のsumと重なってしまうから、ほかの文字にすべきだった
for i in range(N):
sum += abs(to_minutes(matrix[i][0], matrix[i][1]) - to_minutes(matrix[i][2], matrix[i][3]))
#ここ悪い癖だと思うんだけど、すべて長ったらしい配列の座標に直した後に最初の関数で分数に直し、差分をsumに書いていった
hour = str(sum // 60)
minute = str(sum % 60)
print(hour+ " " +minute)
#時と分を空白で区切るやり方がよくわからなくててこずった
2.解法のアプローチ(すべて分に直す)
時間計算(時・分)をそのまま引き算しようとすると「繰り下がり」の計算が面倒になります。
07:11 $\to$ $7 \times 60 + 11 = 431$ 分
17:09 $\to$ $17 \times 60 + 9 = 1029$ 分
滞在時間:$1029 - 431 = 598$ 分
最後に合計分を // 60(時間)と % 60(あまりの分)に戻せば完了です。
3. 改善版コード(素直な for ループ)
変数名の被りを修正し、f-string で出力をスッキリさせたコードです。
N = int(input())
total_h = 0
total_m = 0
for _ in range(N):
e, l = input().split()
e_h, e_m = map(int, e.split(":"))
l_h, l_m = map(int, l.split(":"))
diff_h = l_h - e_h
diff_m = l_m - e_m
# 分がマイナスになったら、1時間(60分)借りて繰り下げる
if diff_m < 0:
diff_m += 60
diff_h -= 1
total_h += diff_h
total_m += diff_m
# 最後に「分」の合計が 60 以上なら「時」へ繰り上げる
total_h += total_m // 60
total_m %= 60
print(f"{total_h} {total_m}")
4. さらにスッキリ&高速に書くなら(スライス利用)
hh:mm のように桁数が固定(5文字)されている場合、split(":") を使わずに文字列スライスで取り出すとさらに高速になります。
import sys
def main():
# 全データを一括取得してスペース・改行で分解
input_data = sys.stdin.read().split()
if not input_data:
return
N = int(input_data[0])
total_minutes = 0
# input_data[1] 以降の入退室ペアを順番に処理
for i in range(1, 2 * N + 1, 2):
e = input_data[i] # 入室 "07:11"
l = input_data[i + 1] # 退室 "17:09"
# スライスで "hh" と "mm" を取り出して「分」に換算
in_m = int(e[:2]) * 60 + int(e[3:])
out_m = int(l[:2]) * 60 + int(l[3:])
total_minutes += (out_m - in_m)
print(f"{total_minutes // 60} {total_minutes % 60}")
if __name__ == "__main__":
main()
5. 学んだこと・まとめ
-
時刻の計算は「最小単位(分や秒)に換算して一括計算」が原則
-
sum や list などの標準組み込み関数名を変数名に使わないよう注意する
-
桁数が固定された文字列(hh:mm など)は、split() よりもスライス([:2], [3:]) を使うとコードが短く処理も速くなる