1use crate::util::hash::*;
3use crate::util::parse::*;
4
5type Input = FastMap<usize, [u32; 60]>;
6
7pub fn parse(input: &str) -> Input {
8 let mut records: Vec<_> = input.lines().map(str::as_bytes).collect();
10 records.sort_unstable();
11
12 let mut id = 0;
14 let mut start = 0;
15 let mut guards = FastMap::new();
16
17 for record in records {
18 match record.len() {
19 31 => start = to_index(&record[15..17]),
20 27 => {
21 let end = to_index(&record[15..17]);
22 let minutes = guards.entry(id).or_insert_with(|| [0; 60]);
23 (start..end).for_each(|i| minutes[i] += 1);
24 }
25 _ => id = to_index(&record[26..record.len() - 13]),
26 }
27 }
28
29 guards
30}
31
32pub fn part1(input: &Input) -> usize {
34 choose(input, |(_, m)| m.iter().sum())
35}
36
37pub fn part2(input: &Input) -> usize {
39 choose(input, |(_, m)| *m.iter().max().unwrap())
40}
41
42fn choose(input: &Input, strategy: impl Fn(&(&usize, &[u32; 60])) -> u32) -> usize {
43 let (id, minutes) = input.iter().max_by_key(strategy).unwrap();
45 let (minute, _) = minutes.iter().enumerate().max_by_key(|(_, m)| **m).unwrap();
47 id * minute
49}
50
51fn to_index(slice: &[u8]) -> usize {
52 slice.iter().fold(0, |acc, n| 10 * acc + n.to_decimal() as usize)
53}