#!/usr/bin/env python from datetime import datetime import re RE_BEGIN = re.compile("^\[(.*)\] Guard #(\d+) begins shift$") RE_SLEEP = re.compile("^\[(.*)\] falls asleep$") RE_AWAKE = re.compile("^\[(.*)\] wakes up$") guards = dict() def read_input(): with open('input.txt', 'r') as f: data = f.read().splitlines() return sorted(data) def convert_time(data): return datetime.strptime(data, '%Y-%m-%d %H:%M') def guard_stop_shift(guard, date): guard_awake(guard, date) def guard_start_shift(guard, date): if guard is None: return if guard not in guards: guards[guard] = { 'guard': guard, 'state': 'awake', 'min': [0]*60, 'sleep': 0, 'last_time': None } guard_awake(guard, date) def guard_sleep(guard, date): if guard is None: return guards[guard]['state'] = 'sleep' guards[guard]['last_time'] = date def guard_awake(guard, date): if guard is None: return if guards[guard]['state'] in ['awake']: guards[guard]['last_time'] = date return m = int((date - guards[guard]['last_time']).total_seconds() / 60) m1 = guards[guard]['last_time'].minute for x in range(m): m2 = (x + m1) % 60 guards[guard]['min'][m2] += 1 guards[guard]['sleep'] += m guards[guard]['state'] = 'awake' guards[guard]['last_time'] = date current_guard = None for line in read_input(): m = RE_BEGIN.match(line) if m: d = convert_time(m.group(1)) guard_stop_shift(current_guard, d) current_guard = (int)(m.group(2)) guard_start_shift(current_guard, d) continue m = RE_SLEEP.match(line) if m: d = convert_time(m.group(1)) guard_sleep(current_guard, d) continue m = RE_AWAKE.match(line) if m: d = convert_time(m.group(1)) guard_awake(current_guard, d) continue print(line) raise Exception('unpasable line') max_min = 0 max_guard = None for g in guards.values(): m = max(g['min']) if m > max_min: max_guard = g max_min = m max_min_pos = [i for i, j in enumerate(max_guard['min']) if j == max_min] print(max_guard['guard'] * max_min_pos[0])