#[macro_use] extern crate lazy_static; extern crate regex; use regex::Regex; use std::collections::HashMap; use std::fs::File; use std::io::{BufRead, BufReader}; type Day4Map = HashMap; fn calc_minutes_from_lines(lines: &mut Vec, map: &mut Day4Map, gid: u16, start: u16) { lazy_static! { static ref GUARD_RE: Regex = Regex::new(r"^\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}\] Guard #(\d+) begins shift$").unwrap(); static ref ASLEEP_RE: Regex = Regex::new(r"^\[\d{4}-\d{2}-\d{2} \d{2}:(\d{2})\] falls asleep$").unwrap(); static ref AWAKE_RE: Regex = Regex::new(r"^\[\d{4}-\d{2}-\d{2} \d{2}:(\d{2})\] wakes up$").unwrap(); } let line = lines.remove(0); let line = line.as_str(); let guard_id = if GUARD_RE.is_match(line) { let caps = GUARD_RE.captures(line).unwrap(); caps[1].parse::().unwrap() } else { gid }; let start_minute = if ASLEEP_RE.is_match(line) { let caps = ASLEEP_RE.captures(line).unwrap(); caps[1].parse::().unwrap() } else { start }; if AWAKE_RE.is_match(line) { let caps = AWAKE_RE.captures(line).unwrap(); let end_minute = caps[1].parse::().unwrap(); map.entry(guard_id) .and_modify(|e| { for minute in (start_minute..end_minute).into_iter() { e[usize::from(minute)] += 1; } }) .or_insert([0u16; 60]); }; if lines.is_empty() { return; } else { calc_minutes_from_lines(lines, map, guard_id, start_minute) } } fn get_max_from_map(map: &mut Day4Map) -> (u16, u16) { let mut count_map: HashMap = HashMap::new(); let mut max_gid = 0; let mut max_count = 0; let mut max_minute = 0; let mut most_max_gid = 0; let mut most_max_minute = 0; let mut most_max_minute_index = 0; for (key, value) in map { let sum = value.into_iter().sum(); if sum > max_count { max_gid = *key; max_count = sum; let mut cur_max_min = 0; for i in 0..value.len() { if value[i] > cur_max_min { cur_max_min = value[i]; max_minute = i as u16; } } } for i in 0..value.len() { if value[i] > most_max_minute { most_max_minute = value[i]; most_max_minute_index = i as u16; most_max_gid = *key; } } count_map.insert(*key, sum); } let part_one = max_gid * max_minute; let part_two = most_max_gid * most_max_minute_index; println!( "max guard id is {} sum {}, max minute of {} with val of {}", max_gid, max_count, max_minute, part_one ); println!( "guard {} most asleep on a single minute {} with a count of {} is {}", most_max_gid, most_max_minute_index, most_max_minute, part_two ); (part_one, part_two) } fn main() { let mut lines: Vec = BufReader::new(File::open("sorted-input").unwrap()) .lines() .map(|line| line.unwrap()) .collect(); let mut map = Day4Map::new(); calc_minutes_from_lines(&mut lines, &mut map, 0, 0); get_max_from_map(&mut map); } #[cfg(test)] mod tests { use super::*; #[test] fn test_part_one() { let mut lines = vec![ String::from("[1518-11-01 00:00] Guard #10 begins shift"), String::from("[1518-11-01 00:05] falls asleep"), String::from("[1518-11-01 00:25] wakes up"), String::from("[1518-11-01 00:30] falls asleep"), String::from("[1518-11-01 00:55] wakes up"), String::from("[1518-11-01 23:58] Guard #99 begins shift"), String::from("[1518-11-02 00:40] falls asleep"), String::from("[1518-11-02 00:50] wakes up"), String::from("[1518-11-03 00:05] Guard #10 begins shift"), String::from("[1518-11-03 00:24] falls asleep"), String::from("[1518-11-03 00:29] wakes up"), String::from("[1518-11-04 00:02] Guard #99 begins shift"), String::from("[1518-11-04 00:36] falls asleep"), String::from("[1518-11-04 00:46] wakes up"), String::from("[1518-11-05 00:03] Guard #99 begins shift"), String::from("[1518-11-05 00:45] falls asleep"), String::from("[1518-11-05 00:55] wakes up"), ]; let mut map = Day4Map::new(); calc_minutes_from_lines(&mut lines, &mut map, 0, 0); let (part_one, part_two) = get_max_from_map(&mut map); assert_eq!(part_one, 240); assert_eq!(part_two, 4455); } }