aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar alecdwm 2018-12-06 13:18:11 +1000
committerGravatar alecdwm 2018-12-06 13:18:11 +1000
commitbdc6fe26ed4eeeca810c7475d01c876b011ecad4 (patch)
treeef5f520bd9c8ba00ba30e21f9e4dc8b8eade0853
parent3612d79c4e4f00887bb284831889e1a4eaa51270 (diff)
added day4 part2 solution
-rw-r--r--src/day4.rs158
-rw-r--r--src/main.rs1
2 files changed, 128 insertions, 31 deletions
diff --git a/src/day4.rs b/src/day4.rs
index e7e36f7..8251040 100644
--- a/src/day4.rs
+++ b/src/day4.rs
@@ -56,9 +56,86 @@ pub fn part1() {
let mut sorted_input: Vec<_> = input.lines().collect();
sorted_input.sort();
- let mut sleep_schedule: BTreeMap<i64, (i64, Vec<i64>)> = BTreeMap::new();
+ let sleep_schedule = build_part_1_sleep_schedule(sorted_input);
+
+ let most_slept_guard = &sleep_schedule
+ .iter()
+ .fold((0, 0), |most_slept, (k, v)| {
+ if most_slept.0 < v.0 {
+ (v.0, *k)
+ } else {
+ most_slept
+ }
+ }).1;
+
+ let mut slept_minutes: BTreeMap<i64, i64> = BTreeMap::new();
+ for minute in &sleep_schedule.get(&most_slept_guard).unwrap().1 {
+ *slept_minutes.entry(*minute).or_insert(0) += 1;
+ }
+
+ let most_slept_minute = slept_minutes
+ .iter()
+ .fold((0, 0), |most_slept, (k, v)| {
+ if most_slept.1 < *v {
+ (*k, *v)
+ } else {
+ most_slept
+ }
+ }).0;
+
+ println!(
+ "the id of the guard ({}) multiplied by the minute ({}): {}",
+ most_slept_guard,
+ most_slept_minute,
+ most_slept_guard * most_slept_minute
+ );
+}
+
+/// Strategy 2: Of all guards, which guard is most frequently asleep on the same minute?
+///
+/// In the example above, Guard #99 spent minute 45 asleep more than any other guard or minute - three times in total. (In all other cases, any guard spent any minute asleep at most twice.)
+///
+/// What is the ID of the guard you chose multiplied by the minute you chose? (In the above example, the answer would be 99 * 45 = 4455.)
+pub fn part2() {
+ let input = ::common::read_stdin_to_string();
+
+ let mut sorted_input: Vec<_> = input.lines().collect();
+ sorted_input.sort();
+
+ let sleep_schedule = build_part_2_sleep_schedule(sorted_input);
+
+ let most_slept_count_and_minute_and_guard =
+ &sleep_schedule
+ .iter()
+ .fold((0, 0, 0), |most_slept, (guard, minutes)| {
+ minutes
+ .iter()
+ .fold(most_slept, |most_slept, (minute, slept_count)| {
+ if most_slept.0 < *slept_count {
+ (*slept_count, *minute, *guard)
+ } else {
+ most_slept
+ }
+ })
+ });
+ let most_slept_minute = most_slept_count_and_minute_and_guard.1;
+ let most_slept_guard = most_slept_count_and_minute_and_guard.2;
+
+ println!(
+ "the id of the guard ({}) multiplied by the minute ({}): {}",
+ most_slept_guard,
+ most_slept_minute,
+ most_slept_guard * most_slept_minute
+ );
+}
+
+fn build_part_1_sleep_schedule<'a, T: IntoIterator<Item = &'a str>>(
+ sorted_input: T,
+) -> BTreeMap<i64, (i64, Vec<i64>)> {
+ let mut sleep_schedule = BTreeMap::new();
let mut guard = 0;
let mut last_minute = 0;
+
for line in sorted_input {
let minute = line
.chars()
@@ -100,38 +177,57 @@ pub fn part1() {
}
}
- let most_slept_guard = sleep_schedule
- .iter()
- .fold((0, 0), |most_slept, (k, v)| {
- if most_slept.0 < v.0 {
- (v.0, *k)
- } else {
- most_slept
+ sleep_schedule
+}
+
+fn build_part_2_sleep_schedule<'a, T: IntoIterator<Item = &'a str>>(
+ sorted_input: T,
+) -> BTreeMap<i64, BTreeMap<i64, i64>> {
+ let mut sleep_schedule = BTreeMap::new();
+ let mut guard = 0;
+ let mut last_minute = 0;
+
+ for line in sorted_input {
+ let minute = line
+ .chars()
+ .skip(15)
+ .take(2)
+ .collect::<String>()
+ .parse::<i64>()
+ .unwrap();
+
+ match line.split(' ').skip(2).next().unwrap() {
+ "Guard" => {
+ guard = line
+ .split(' ')
+ .skip(3)
+ .next()
+ .unwrap()
+ .chars()
+ .skip(1)
+ .collect::<String>()
+ .parse::<i64>()
+ .unwrap();
}
- }).1;
+ "falls" => {
+ last_minute = minute;
+ }
+ "wakes" => {
+ let guard_entry = sleep_schedule.entry(guard).or_insert(BTreeMap::new());
+ let mut minutes_slept = minute - last_minute;
+ while minutes_slept < 0 {
+ minutes_slept = 60 - minutes_slept;
+ }
- let mut slept_minutes: BTreeMap<i64, i64> = BTreeMap::new();
- for minute in &sleep_schedule
- .entry(most_slept_guard)
- .or_insert((0, Vec::new()))
- .1
- {
- *slept_minutes.entry(*minute).or_insert(0) += 1;
- }
- let most_slept_minute = slept_minutes
- .iter()
- .fold((0, 0), |most_slept, (k, v)| {
- if most_slept.1 < *v {
- (*k, *v)
- } else {
- most_slept
+ for min in last_minute..(last_minute + minutes_slept) {
+ *guard_entry.entry(min % 60).or_insert(0) += 1
+ }
+
+ last_minute = minute;
}
- }).0;
+ _ => panic!("unhandled input: {}", line),
+ }
+ }
- println!(
- "the id of the guard ({}) multiplied by the minute ({}): {}",
- most_slept_guard,
- most_slept_minute,
- most_slept_guard * most_slept_minute
- );
+ sleep_schedule
}
diff --git a/src/main.rs b/src/main.rs
index 6c9513d..440bdcd 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -17,6 +17,7 @@ fn main() {
puzzle_solution_map.insert("day3::part1", advent_of_code_2018::day3::part1);
puzzle_solution_map.insert("day3::part2", advent_of_code_2018::day3::part2);
puzzle_solution_map.insert("day4::part1", advent_of_code_2018::day4::part1);
+ puzzle_solution_map.insert("day4::part2", advent_of_code_2018::day4::part2);
let command = args[1].as_str();
if command == "list" {