extern crate advent_of_code_2018; use advent_of_code_2018::*; use std::str::FromStr; use std::error::Error; use std::path::PathBuf; use std::collections::HashMap; // cargo watch -cs "cargo run --release --bin day_4" #[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] struct Event { date: String, hour: u32, minute: u32, what: EventType } #[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] enum EventType { BeginShift(u32), Asleep, Awake } impl FromStr for Event { type Err = Box; fn from_str(s: &str) -> Result { let date = s.split_whitespace().nth(0).unwrap().trim_matches('[').to_string(); let time = s.split_whitespace().nth(1).unwrap().trim_matches(']'); let hour = time.split(':').nth(0).unwrap().parse().unwrap(); let minute = time.split(':').nth(1).unwrap().parse().unwrap(); let guard = s.split_whitespace().nth(3).and_then(|x| x.trim_matches('#').parse().ok()); let what = match s.split_whitespace().nth(2).unwrap() { "Guard" => EventType::BeginShift(guard.unwrap()), "falls" => EventType::Asleep, "wakes" => EventType::Awake, _ => panic!("Unknown event") }; Ok(Event { date, hour, minute, what }) } } #[derive(Debug)] struct GuardSleepStats { per_minute: HashMap } impl GuardSleepStats { fn new() -> GuardSleepStats { GuardSleepStats { per_minute: HashMap::new() } } fn total(&self) -> u32 { self.per_minute.values().sum() } } fn main() -> Result<(), Box> { let input = read_file(&PathBuf::from("inputs/4.txt"))?; //println!("Input: {:?}", input); let mut events: Vec = input.iter().map(|line| line.parse().unwrap()).collect(); events.sort(); //println!("Events: {:?}", events); let mut sleep = HashMap::new(); let mut current_guard = 0; let mut last_asleep = 0; for event in events { match event.what { EventType::BeginShift(guard) => current_guard = guard, EventType::Asleep => last_asleep = event.minute, EventType::Awake => { for i in last_asleep..event.minute { *sleep .entry(current_guard) .or_insert(GuardSleepStats::new()) .per_minute .entry(i) .or_insert(0) += 1 } } } } println!("Stats: {:?}", sleep); let (sleepiest_guard, sleepiest_stats) = sleep.iter().max_by_key(|(_,v)| v.total()).unwrap().clone(); println!("Sleepiest guard: {:?}", sleepiest_guard); let (sleepiest_minute, sleepiest_occurances) = sleepiest_stats.per_minute.iter().max_by_key(|(_,v)| *v).unwrap().clone(); println!("Sleepiest minute: {:?}", sleepiest_minute); println!("Part 1 answer: {}", sleepiest_guard * sleepiest_minute); let (specific_minute_offender, specific_minute_stats) = sleep.iter().max_by_key(|(_,v)| v.per_minute.values().max().unwrap()).unwrap().clone(); println!("Specific minute: {:?}", specific_minute_offender); let (specific_minute_minute, specific_minute_occurances) = specific_minute_stats.per_minute.iter().max_by_key(|(_,v)| *v).unwrap().clone(); println!("Specific Minute minute: {:?}", specific_minute_minute); println!("Part 2 answer: {}", specific_minute_offender * specific_minute_minute); Ok(()) }