-
Notifications
You must be signed in to change notification settings - Fork 5
/
day04.rs
53 lines (44 loc) · 1.59 KB
/
day04.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//! # Repose Record
use crate::util::hash::*;
use crate::util::parse::*;
type Input = FastMap<usize, [u32; 60]>;
pub fn parse(input: &str) -> Input {
// Records need to be in chronological order.
let mut records: Vec<_> = input.lines().map(str::as_bytes).collect();
records.sort_unstable();
// Build each sleep schedule
let mut id = 0;
let mut start = 0;
let mut guards = FastMap::new();
for record in records {
match record.len() {
31 => start = to_index(&record[15..17]),
27 => {
let end = to_index(&record[15..17]);
let minutes = guards.entry(id).or_insert_with(|| [0; 60]);
(start..end).for_each(|i| minutes[i] += 1);
}
_ => id = to_index(&record[26..record.len() - 13]),
}
}
guards
}
/// Find the guard with the greatest total minutes asleep.
pub fn part1(input: &Input) -> usize {
choose(input, |(_, m)| m.iter().sum())
}
/// Find the guard with the highest single minute asleep.
pub fn part2(input: &Input) -> usize {
choose(input, |(_, m)| *m.iter().max().unwrap())
}
fn choose(input: &Input, strategy: impl Fn(&(&usize, &[u32; 60])) -> u32) -> usize {
// Find the guard using a specific strategy.
let (id, minutes) = input.iter().max_by_key(strategy).unwrap();
// Find the minute spent asleep the most
let (minute, _) = minutes.iter().enumerate().max_by_key(|(_, m)| **m).unwrap();
// Return result
id * minute
}
fn to_index(slice: &[u8]) -> usize {
slice.iter().fold(0, |acc, n| 10 * acc + n.to_decimal() as usize)
}