use chrono::prelude::*; use chrono::Duration; use chrono::NaiveDateTime; use std::collections::HashMap; use crate::utils; enum Activity { Starts(u32), FallsAsleep, Awakens, } #[derive(PartialEq)] enum State { Asleep, Awake, } pub fn task1() { use self::Activity::*; let input = utils::read_file("input/day04.txt"); let mut input: Vec<_> = input .lines() .map(|line| { // [1518-10-26 00:01] Guard #1069 begins shift let time = NaiveDateTime::parse_from_str(&line[1..=16], "%Y-%m-%d %H:%M").unwrap(); let activity = if line.contains("falls asleep") { Activity::FallsAsleep } else if line.contains("wakes up") { Activity::Awakens } else { let number: u32 = line.split(' ').find(|part| part.starts_with("#")).unwrap()[1..] .parse() .unwrap(); Activity::Starts(number) }; (time, activity) }).collect(); input.sort_by_key(|it| it.0); let mut current_id: u32 = 0; let mut current_state = State::Awake; let mut last_time = input[0].0; let mut sleep_map: HashMap = HashMap::new(); let minute = Duration::minutes(1); for (time, activity) in input.into_iter() { // for all minutes since last time slot fill arrays let mut iter_time = last_time.clone(); while iter_time < time { if current_state == State::Asleep && iter_time.hour() == 0 { sleep_map.entry(current_id).or_insert([0; 60])[iter_time.minute() as usize] += 1; } iter_time += minute; } match activity { Starts(id) => { current_state = State::Awake; current_id = id; } FallsAsleep => current_state = State::Asleep, Awakens => current_state = State::Awake, } last_time = time; } let sleeper = sleep_map .iter() .map(|(id, schedule)| (id, schedule.iter().sum::())) .max_by_key(|it| it.1) .unwrap(); println!("Sleeper: {:?}", sleeper); let worst_minute = sleep_map .get(sleeper.0) .unwrap() .iter() .enumerate() .max_by_key(|it| it.1) .unwrap() .0; println!("Worst minute: {}", worst_minute); println!("Result: {}", *sleeper.0 as usize * worst_minute); } pub fn task2() { use self::Activity::*; let input = utils::read_file("input/day04.txt"); let mut input: Vec<_> = input .lines() .map(|line| { // [1518-10-26 00:01] Guard #1069 begins shift let time = NaiveDateTime::parse_from_str(&line[1..=16], "%Y-%m-%d %H:%M").unwrap(); let activity = if line.contains("falls asleep") { Activity::FallsAsleep } else if line.contains("wakes up") { Activity::Awakens } else { let number: u32 = line.split(' ').find(|part| part.starts_with("#")).unwrap()[1..] .parse() .unwrap(); Activity::Starts(number) }; (time, activity) }).collect(); input.sort_by_key(|it| it.0); let mut current_id: u32 = 0; let mut current_state = State::Awake; let mut last_time = input[0].0; let mut sleep_map: HashMap = HashMap::new(); let minute = Duration::minutes(1); for (time, activity) in input.into_iter() { // for all minutes since last time slot fill arrays let mut iter_time = last_time.clone(); while iter_time < time { if current_state == State::Asleep && iter_time.hour() == 0 { sleep_map.entry(current_id).or_insert([0; 60])[iter_time.minute() as usize] += 1; } iter_time += minute; } match activity { Starts(id) => { current_state = State::Awake; current_id = id; } FallsAsleep => current_state = State::Asleep, Awakens => current_state = State::Awake, } last_time = time; } let sleeper = sleep_map .iter() .max_by_key(|(_, array)| array.iter().max()) .unwrap(); let worst_minute = sleeper .1 .iter() .enumerate() .max_by_key(|it| it.1) .unwrap() .0; println!("Result 2: {}", *sleeper.0 as usize * worst_minute); }