This commit is contained in:
2018-12-17 09:12:33 +01:00
parent 1fd77f3b83
commit e6cd5a020d
46 changed files with 1726 additions and 0 deletions

176
2018/04/src/main.rs Normal file
View File

@@ -0,0 +1,176 @@
use std::collections::HashMap;
use std::io::{self, BufRead};
use chrono::prelude::*;
use regex::{Captures, Regex};
#[derive(Debug)]
struct Entry {
date: DateTime<Utc>,
event: Event,
}
#[derive(Debug)]
enum Event {
BeginShift { guard_id: u16 },
FallsAsleep,
WakesUp,
}
enum State {
Default,
Guard(u16),
FallsAsleep(u16, DateTime<Utc>),
}
fn date_from_captures(caps: &Captures<'_>) -> DateTime<Utc> {
let year = caps
.get(1)
.expect("faild to find year")
.as_str()
.parse::<i32>()
.expect("faild to parse year");
let month = caps
.get(2)
.expect("faild to find month")
.as_str()
.parse::<u32>()
.expect("faild to parse month");
let day = caps
.get(3)
.expect("failed to find day")
.as_str()
.parse::<u32>()
.expect("faild to parse day");
let hour = caps
.get(4)
.expect("faild to find hour")
.as_str()
.parse::<u32>()
.expect("faild to parse hour");
let minute = caps
.get(5)
.expect("failed to find minute")
.as_str()
.parse::<u32>()
.expect("faild to parse minute");
Utc.ymd(year, month, day).and_hms(hour, minute, 0)
}
fn main() {
let re_begin_shift =
Regex::new(r"\[(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})\] Guard #(\d+) begins shift")
.expect("failed to build regex");
let re_falls_asleep = Regex::new(r"\[(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})\] falls asleep")
.expect("failed to build regex");
let re_wakes_up = Regex::new(r"\[(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})\] wakes up")
.expect("failed to build regex");
let mut entries = io::stdin()
.lock()
.lines()
.filter_map(Result::ok)
.map(|line| {
if let Some(caps) = re_begin_shift.captures(&line) {
Entry {
date: date_from_captures(&caps),
event: Event::BeginShift {
guard_id: caps
.get(6)
.expect("failed to find y")
.as_str()
.parse::<u16>()
.expect("faild to parse y"),
},
}
} else if let Some(caps) = re_falls_asleep.captures(&line) {
Entry {
date: date_from_captures(&caps),
event: Event::FallsAsleep,
}
} else if let Some(caps) = re_wakes_up.captures(&line) {
Entry {
date: date_from_captures(&caps),
event: Event::WakesUp,
}
} else {
panic!("failed to parse line: {}", line);
}
})
.collect::<Vec<_>>();
entries.sort_by_key(|entry| entry.date);
let entries = entries;
let mut minute_asleep = HashMap::new();
let mut minutes_asleep = HashMap::new();
let mut state = State::Default;
for entry in &entries {
match (state, &entry.event) {
// Default.
(State::Default, Event::BeginShift { guard_id }) => {
state = State::Guard(*guard_id);
}
(State::Default, _) => panic!("oh no"),
// Guard.
(State::Guard(_), Event::BeginShift { guard_id }) => state = State::Guard(*guard_id),
(State::Guard(guard_id), Event::FallsAsleep) => {
state = State::FallsAsleep(guard_id, entry.date);
}
(State::Guard(_), _) => panic!("oh no"),
// FallsAsleep.
(State::FallsAsleep(guard_id, date), Event::WakesUp) => {
state = State::Guard(guard_id);
for m in date.minute()..entry.date.minute() {
minute_asleep
.entry((guard_id, m))
.and_modify(|x| *x += 1)
.or_insert(1);
}
let duration = entry.date - date;
minutes_asleep
.entry(guard_id)
.and_modify(|x| *x += duration.num_seconds())
.or_insert(0);
}
(State::FallsAsleep(_, _), _) => panic!("oh no"),
}
}
let (guard_id, minutes) = minutes_asleep
.iter()
.max_by_key(|(_, asleep)| *asleep)
.expect("failed to find guard");
let (minute, _) = minute_asleep
.iter()
.filter(|((guard, _), _)| guard == guard_id)
.map(|((_, minute), total)| (minute, total))
.max_by_key(|(minute, total)| *total)
.expect("failed to find minute");
println!("part.one={}", *guard_id as u32 * *minute);
let (guard_id, minute, _) = minute_asleep
.iter()
.map(|((guard, minute), total)| (guard, minute, total))
.max_by_key(|(guard, minute, total)| *total)
.expect("failed to find guard and minute");
println!("part.two={}", *guard_id as u32 * *minute);
}