mirror of
https://github.com/wezm/advent-of-code.git
synced 2024-12-18 18:29:55 +00:00
Add day 4 2018 part 2
This commit is contained in:
parent
3017e4bd43
commit
bf93a2b8ae
1 changed files with 83 additions and 24 deletions
|
@ -3,10 +3,10 @@ extern crate lazy_static;
|
||||||
extern crate chrono;
|
extern crate chrono;
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
|
|
||||||
use chrono::{DateTime, TimeZone, Utc, Duration, Timelike};
|
use chrono::{DateTime, Duration, TimeZone, Timelike, Utc};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::fs;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Action {
|
enum Action {
|
||||||
|
@ -21,6 +21,14 @@ struct Entry {
|
||||||
action: Action,
|
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() {
|
fn main() {
|
||||||
let input = fs::read_to_string("input/day4.txt").expect("input");
|
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.sort_unstable_by(|a, b| a.time.cmp(&b.time));
|
||||||
entries
|
entries
|
||||||
};
|
};
|
||||||
|
let entries_by_guard = entries_by_guard(&entries);
|
||||||
|
|
||||||
part1(&entries);
|
part1(&entries_by_guard);
|
||||||
|
part2(&entries_by_guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part1(entries: &[Entry]) {
|
fn part1(entries_by_guard: &HashMap<u32, Vec<&Entry>>) {
|
||||||
// First group entries by guard
|
// Find the one that was asleep the most
|
||||||
let entries_by_guard = entries_by_guard(entries);
|
|
||||||
|
|
||||||
// Next find the one that was asleep the most
|
|
||||||
let guards_by_time_asleep = calculate_time_asleep(&entries_by_guard);
|
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));
|
let asleep_the_most = guards_by_time_asleep.iter().max_by(
|
||||||
println!("{:?}", asleep_the_most);
|
|(_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
|
// Now find the minute that guard is asleep the most
|
||||||
let sleepiest_guard = asleep_the_most.unwrap().0;
|
let sleepiest_guard = asleep_the_most.unwrap().0;
|
||||||
let sleep_by_minute = sleep_by_minute(&entries_by_guard[sleepiest_guard]);
|
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>> {
|
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;
|
let mut current_guard = None;
|
||||||
|
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
println!("{:?}", entry);
|
|
||||||
|
|
||||||
match entry.action {
|
match entry.action {
|
||||||
Action::BeginShift(guard_id) => {
|
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);
|
guard_entry.push(entry);
|
||||||
current_guard = Some(guard_id);
|
current_guard = Some(guard_id);
|
||||||
}
|
}
|
||||||
Action::FallAsleep => {
|
Action::FallAsleep => {
|
||||||
entries_by_guard.get_mut(¤t_guard.unwrap()).unwrap().push(entry);
|
entries_by_guard
|
||||||
|
.get_mut(¤t_guard.unwrap())
|
||||||
|
.unwrap()
|
||||||
|
.push(entry);
|
||||||
}
|
}
|
||||||
Action::WakeUp => {
|
Action::WakeUp => {
|
||||||
entries_by_guard.get_mut(¤t_guard.unwrap()).unwrap().push(entry);
|
entries_by_guard
|
||||||
|
.get_mut(¤t_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 {
|
for entry in entries {
|
||||||
match entry.action {
|
match entry.action {
|
||||||
Action::BeginShift(guard_id) => {}
|
Action::BeginShift(_guard_id) => {}
|
||||||
Action::FallAsleep => fell_asleep = Some(entry.time),
|
Action::FallAsleep => fell_asleep = Some(entry.time),
|
||||||
Action::WakeUp => {
|
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());
|
*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 {
|
for entry in entries {
|
||||||
match entry.action {
|
match entry.action {
|
||||||
Action::BeginShift(guard_id) => {}
|
Action::BeginShift(_guard_id) => {}
|
||||||
Action::FallAsleep => fell_asleep = Some(entry.time),
|
Action::FallAsleep => fell_asleep = Some(entry.time),
|
||||||
Action::WakeUp => {
|
Action::WakeUp => {
|
||||||
for minute in fell_asleep.unwrap().minute()..entry.time.minute() {
|
for minute in fell_asleep.unwrap().minute()..entry.time.minute() {
|
||||||
|
@ -141,8 +198,10 @@ fn parse_entry(line: &str) -> Option<Entry> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entry {
|
fn max_minute(hash: &HashMap<u32, u32>) -> (u32, u32) {
|
||||||
fn new(time: DateTime<Utc>, action: Action) -> Self {
|
hash
|
||||||
Self { time, action }
|
.iter()
|
||||||
}
|
.max_by(|(_, count), (_, other_count)| count.cmp(other_count))
|
||||||
|
.map(|(&minute, &count)| (minute, count))
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue