From d139374ef1518c5bd4e5c84e1d88263fdda2e15c Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Tue, 4 Dec 2018 16:17:14 +0100 Subject: Day 4 --- 2018/src/day4.rs | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2018/src/main.rs | 6 ++- 2 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 2018/src/day4.rs (limited to '2018/src') diff --git a/2018/src/day4.rs b/2018/src/day4.rs new file mode 100644 index 0000000..90cab72 --- /dev/null +++ b/2018/src/day4.rs @@ -0,0 +1,134 @@ +use std::io; +use std::io::BufRead; +use std::collections::HashMap; +use std::cmp::max; +use regex::Regex; + +#[derive(PartialEq, Eq, PartialOrd, Ord)] +enum Action { + Begin(i32), + Sleep, + Wake +} + +#[derive(PartialEq, Eq, PartialOrd, Ord)] +struct Record { + year: i32, + month: i32, + day: i32, + hour: i32, + minute: i32, + action: Action +} + +struct Guard { + id: i32, + sleep_times: Vec<(i32, i32)>, // inclusive-exclusive + asleep: [i32; 60] +} + +fn parse_action(line: &str) -> Action { + if line.chars().next() == Some('G') { + let idx = 7 + line[7..].find(' ').unwrap(); + Action::Begin(line[7 .. idx].parse().unwrap()) + } else if line.chars().next() == Some('f') { + Action::Sleep + } else { + Action::Wake + } +} + +fn parse_line(line: &str) -> Record { + lazy_static! { + static ref RE: Regex = Regex::new(r"^\[(\d+)-(\d+)-(\d+) (\d+):(\d+)\] (.*)$").unwrap(); + } + + let caps = RE.captures(line).unwrap(); + Record { + year: caps.get(1).unwrap().as_str().parse().unwrap(), + month: caps.get(2).unwrap().as_str().parse().unwrap(), + day: caps.get(3).unwrap().as_str().parse().unwrap(), + hour: caps.get(4).unwrap().as_str().parse().unwrap(), + minute: caps.get(5).unwrap().as_str().parse().unwrap(), + action: parse_action(caps.get(6).unwrap().as_str()) + } +} + +fn argmax(v: &[T]) -> Option { + if v.len() == 0 { + None + } else { + let mut maxat = 0; + for i in 1..v.len() { + if v[i] > v[maxat] { + maxat = i; + } + } + Some(maxat) + } +} + +pub fn main(reader: T) -> io::Result<()> { + let mut records: Vec = reader.lines().map(|l| parse_line(&l.unwrap())).collect(); + + records.sort_unstable(); + let mut guards = HashMap::new(); + + { + let mut current_id = 0; + let mut sleep_start = 0; + + for record in records.iter() { + match record.action { + Action::Begin(id) => { + if let None = guards.get(&id) { + guards.insert(id, Guard {id: id, sleep_times: Vec::new(), asleep: [0; 60]}); + } + current_id = id; + }, + Action::Sleep => sleep_start = record.minute, + Action::Wake => + guards.get_mut(¤t_id).unwrap() + .sleep_times.push((sleep_start, record.minute)) + } + } + } + + let mut max_sleep = -1; + let mut max_sleep_at = -1; + let mut max_times = -1; + let mut max_times_at = -1; + + for mut guard in guards.values_mut() { + let mut sleep = 0; + let mut times = 0; + + for (from, to) in guard.sleep_times.iter() { + for i in *from..*to { + guard.asleep[i as usize] += 1; + times = max(times, guard.asleep[i as usize]); + } + sleep += to - from; + } + + if sleep > max_sleep { + max_sleep = sleep; + max_sleep_at = guard.id; + } + + if times > max_times { + max_times = times; + max_times_at = guard.id; + } + } + + let sleepy_guard = guards.get(&max_sleep_at).unwrap(); + let max_minute = argmax(&sleepy_guard.asleep).unwrap() as i32; + println!("{}", max_minute * sleepy_guard.id); + + let consistent_guard = guards.get(&max_times_at).unwrap(); + let max_minute = argmax(&consistent_guard.asleep).unwrap() as i32; + println!("{}", max_minute * consistent_guard.id); + + Ok(()) +} diff --git a/2018/src/main.rs b/2018/src/main.rs index 349d857..98c0f7b 100644 --- a/2018/src/main.rs +++ b/2018/src/main.rs @@ -1,3 +1,5 @@ +#[macro_use] extern crate lazy_static; +extern crate regex; extern crate argparse; use std::io; @@ -9,12 +11,14 @@ use argparse::{ArgumentParser, StoreTrue, Store}; mod day1; mod day2; mod day3; +mod day4; fn day_switch(day: i32, reader: T) -> io::Result<()> { match day { 1 => day1::main(reader), 2 => day2::main(reader), 3 => day3::main(reader), + 4 => day4::main(reader), _ => Err(Error::new(ErrorKind::Other, "Invalid day")) } } @@ -70,7 +74,7 @@ fn main() -> io::Result<()> { error_handler(|| if day_string.len() == 0 { - for day in 1..4 { + for day in 1..5 { run_day(day, &options)?; } Ok(()) -- cgit v1.2.3-70-g09d2