advent_of_code/year2018/
day04.rs1use crate::input::Input;
2use std::collections::HashMap;
3
4enum EntryType {
5 BeginShift { guard_id: u32 },
6 FallsAsleep,
7 WakesUp,
8}
9
10struct LogEntry {
11 minute: u32,
12 entry: EntryType,
13}
14
15fn parse_input(input_string: &str) -> Result<Vec<LogEntry>, String> {
16 let mut lines: Vec<&str> = input_string.lines().collect();
17 lines.sort_unstable();
18
19 lines
20 .iter()
21 .enumerate()
22 .map(|(line_index, line)| {
23 let error_message = || format!("Incorrect input at line {}", line_index + 1);
24 let parts: Vec<&str> = line.split_whitespace().collect();
25 if parts.len() < 4 || parts[1].len() != 6 {
26 return Err(error_message());
27 }
28
29 let minute = parts[1][3..5].parse().map_err(|_| error_message())?;
30
31 let entry = match *parts.last().ok_or("Internal error: No last value")? {
32 "shift" => EntryType::BeginShift {
33 guard_id: parts[3][1..].parse().map_err(|_| error_message())?,
34 },
35 "asleep" => EntryType::FallsAsleep,
36 "up" => EntryType::WakesUp,
37 _ => {
38 return Err(error_message());
39 }
40 };
41
42 Ok(LogEntry { minute, entry })
43 })
44 .collect()
45}
46
47pub fn solve(input: &Input) -> Result<u32, String> {
48 let entries = parse_input(input.text)?;
49
50 let mut sleepers = HashMap::new();
51 let mut current_guard = 0;
52 let mut start_minute = 0;
53
54 for log_entry in entries.iter() {
55 match log_entry.entry {
56 EntryType::BeginShift { guard_id } => current_guard = guard_id,
57 EntryType::FallsAsleep => start_minute = log_entry.minute,
58 EntryType::WakesUp => {
59 let sleep_record = sleepers.entry(current_guard).or_insert_with(|| vec![0; 61]);
60 for minute in start_minute..log_entry.minute {
61 sleep_record[minute as usize] += 1;
62 }
63 }
64 }
65 }
66
67 if input.is_part_one() {
68 let (&most_sleepy_guard, sleep_record) = sleepers
69 .iter()
70 .max_by_key(|(_key, value)| value.iter().sum::<i32>())
71 .ok_or("Internal error: No most sleep guard")?;
72 let most_sleepy_minute = sleep_record
73 .iter()
74 .enumerate()
75 .max_by_key(|(_minute, count)| *count)
76 .ok_or("Internal error: No most sleepy minute")?
77 .0 as u32;
78
79 Ok(most_sleepy_guard * most_sleepy_minute)
80 } else {
81 let mut highest_sleep_count = -1;
82 let mut sleepiest_guard_id = 0;
83 let mut most_sleepy_minute = 0;
84 for (&guard_id, sleep_record) in sleepers.iter() {
85 let (sleepy_minute, &sleep_count) = sleep_record
86 .iter()
87 .enumerate()
88 .max_by_key(|(_minute, count)| *count)
89 .ok_or("No sleep record for guard")?;
90 if sleep_count > highest_sleep_count {
91 highest_sleep_count = sleep_count;
92 sleepiest_guard_id = guard_id;
93 most_sleepy_minute = sleepy_minute;
94 }
95 }
96 Ok(sleepiest_guard_id * most_sleepy_minute as u32)
97 }
98}
99
100#[test]
101fn tests() {
102 use crate::input::{test_part_one, test_part_two};
103
104 test_part_one!(
105 "[1518-11-01 00:00] Guard #10 begins shift
106[1518-11-01 00:05] falls asleep
107[1518-11-01 00:25] wakes up
108[1518-11-01 00:30] falls asleep
109[1518-11-01 00:55] wakes up
110[1518-11-01 23:58] Guard #99 begins shift
111[1518-11-02 00:40] falls asleep
112[1518-11-02 00:50] wakes up
113[1518-11-03 00:05] Guard #10 begins shift
114[1518-11-03 00:24] falls asleep
115[1518-11-03 00:29] wakes up
116[1518-11-04 00:02] Guard #99 begins shift
117[1518-11-04 00:36] falls asleep
118[1518-11-04 00:46] wakes up
119[1518-11-05 00:03] Guard #99 begins shift
120[1518-11-05 00:45] falls asleep
121[1518-11-05 00:55] wakes up"
122 => 240
123 );
124
125 let input = include_str!("day04_input.txt");
126 test_part_one!(input => 84834);
127
128 test_part_two!(
129 "[1518-11-01 00:00] Guard #10 begins shift
130[1518-11-01 00:05] falls asleep
131[1518-11-01 00:25] wakes up
132[1518-11-01 00:30] falls asleep
133[1518-11-01 00:55] wakes up
134[1518-11-01 23:58] Guard #99 begins shift
135[1518-11-02 00:40] falls asleep
136[1518-11-02 00:50] wakes up
137[1518-11-03 00:05] Guard #10 begins shift
138[1518-11-03 00:24] falls asleep
139[1518-11-03 00:29] wakes up
140[1518-11-04 00:02] Guard #99 begins shift
141[1518-11-04 00:36] falls asleep
142[1518-11-04 00:46] wakes up
143[1518-11-05 00:03] Guard #99 begins shift
144[1518-11-05 00:45] falls asleep
145[1518-11-05 00:55] wakes up"
146 =>4455
147 );
148
149 test_part_two!(input => 53427);
150}