Add day 4 2018 part 2

This commit is contained in:
Wesley Moore 2018-12-11 18:58:41 +11:00
parent 3017e4bd43
commit bf93a2b8ae
No known key found for this signature in database
GPG key ID: BF67766C0BC2D0EE

View file

@ -3,10 +3,10 @@ extern crate lazy_static;
extern crate chrono;
extern crate regex;
use chrono::{DateTime, TimeZone, Utc, Duration, Timelike};
use chrono::{DateTime, Duration, TimeZone, Timelike, Utc};
use regex::Regex;
use std::fs;
use std::collections::HashMap;
use std::fs;
#[derive(Debug)]
enum Action {
@ -21,6 +21,14 @@ struct Entry {
action: Action,
}
impl Entry {
fn new(time: DateTime<Utc>, action: Action) -> Self {
Self { time, action }
}
}
// If anyone is reading this, it's not great Rust code...
fn main() {
let input = fs::read_to_string("input/day4.txt").expect("input");
@ -33,25 +41,66 @@ fn main() {
entries.sort_unstable_by(|a, b| a.time.cmp(&b.time));
entries
};
let entries_by_guard = entries_by_guard(&entries);
part1(&entries);
part1(&entries_by_guard);
part2(&entries_by_guard);
}
fn part1(entries: &[Entry]) {
// First group entries by guard
let entries_by_guard = entries_by_guard(entries);
// Next find the one that was asleep the most
fn part1(entries_by_guard: &HashMap<u32, Vec<&Entry>>) {
// Find the one that was asleep the most
let guards_by_time_asleep = calculate_time_asleep(&entries_by_guard);
let asleep_the_most = guards_by_time_asleep.iter().max_by(|(_guard_id, time_asleep), (_other_guard_id, other_time_asleep)| time_asleep.cmp(other_time_asleep));
println!("{:?}", asleep_the_most);
let asleep_the_most = guards_by_time_asleep.iter().max_by(
|(_guard_id, time_asleep), (_other_guard_id, other_time_asleep)| {
time_asleep.cmp(other_time_asleep)
},
);
// Now find the minute that guard is asleep the most
let sleepiest_guard = asleep_the_most.unwrap().0;
let sleep_by_minute = sleep_by_minute(&entries_by_guard[sleepiest_guard]);
let sleepiest_minute = sleep_by_minute.iter().max_by(|(_minute, count), (_other_minute, other_count)| count.cmp(other_count)).unwrap();
let sleepiest_minute = sleep_by_minute
.iter()
.max_by(|(_minute, count), (_other_minute, other_count)| count.cmp(other_count))
.unwrap();
println!("Day 1: {}", sleepiest_minute.0 * sleepiest_guard);
println!("Part 1: {}", sleepiest_minute.0 * sleepiest_guard);
}
fn part2(entries_by_guard: &HashMap<u32, Vec<&Entry>>) {
let results: HashMap<_, _> = entries_by_guard
.keys()
.filter_map(|guard_id| {
let sleep_by_minute = sleep_by_minute(&entries_by_guard[&guard_id]);
if sleep_by_minute.is_empty() {
None
} else {
Some((guard_id, sleep_by_minute))
}
})
.collect();
// Now find the answer
if let Some((guard_id, minute_counts)) =
results
.iter()
.max_by(|(_, minute_counts), (_, other_minute_counts)| {
max_minute(&minute_counts)
.1
.cmp(&max_minute(&other_minute_counts).1)
})
{
let minute = max_minute(minute_counts).0;
println!(
"Part 2: guard {} * minute {} = {}",
*guard_id,
minute,
*guard_id * minute
);
} else {
println!("Part 2: No result found");
}
}
fn entries_by_guard(entries: &[Entry]) -> HashMap<u32, Vec<&Entry>> {
@ -59,19 +108,25 @@ fn entries_by_guard(entries: &[Entry]) -> HashMap<u32, Vec<&Entry>> {
let mut current_guard = None;
for entry in entries {
println!("{:?}", entry);
match entry.action {
Action::BeginShift(guard_id) => {
let guard_entry = entries_by_guard.entry(guard_id).or_insert_with(|| Vec::new());
let guard_entry = entries_by_guard
.entry(guard_id)
.or_insert_with(|| Vec::new());
guard_entry.push(entry);
current_guard = Some(guard_id);
}
Action::FallAsleep => {
entries_by_guard.get_mut(&current_guard.unwrap()).unwrap().push(entry);
entries_by_guard
.get_mut(&current_guard.unwrap())
.unwrap()
.push(entry);
}
Action::WakeUp => {
entries_by_guard.get_mut(&current_guard.unwrap()).unwrap().push(entry);
entries_by_guard
.get_mut(&current_guard.unwrap())
.unwrap()
.push(entry);
}
}
}
@ -87,10 +142,12 @@ fn calculate_time_asleep(entries_by_guard: &HashMap<u32, Vec<&Entry>>) -> HashMa
for entry in entries {
match entry.action {
Action::BeginShift(guard_id) => {}
Action::BeginShift(_guard_id) => {}
Action::FallAsleep => fell_asleep = Some(entry.time),
Action::WakeUp => {
let total_time_asleep = time_asleep.entry(guard_id).or_insert_with(|| Duration::zero());
let total_time_asleep = time_asleep
.entry(guard_id)
.or_insert_with(|| Duration::zero());
*total_time_asleep = *total_time_asleep + (entry.time - fell_asleep.unwrap());
}
}
@ -106,7 +163,7 @@ fn sleep_by_minute(entries: &[&Entry]) -> HashMap<u32, u32> {
for entry in entries {
match entry.action {
Action::BeginShift(guard_id) => {}
Action::BeginShift(_guard_id) => {}
Action::FallAsleep => fell_asleep = Some(entry.time),
Action::WakeUp => {
for minute in fell_asleep.unwrap().minute()..entry.time.minute() {
@ -141,8 +198,10 @@ fn parse_entry(line: &str) -> Option<Entry> {
}
}
impl Entry {
fn new(time: DateTime<Utc>, action: Action) -> Self {
Self { time, action }
}
fn max_minute(hash: &HashMap<u32, u32>) -> (u32, u32) {
hash
.iter()
.max_by(|(_, count), (_, other_count)| count.cmp(other_count))
.map(|(&minute, &count)| (minute, count))
.unwrap()
}