1use std::array::from_fn;
6
7use crate::util::parse::*;
8
9type Input = (usize, usize);
10
11struct Item {
12 label: usize,
13 lens: usize,
14}
15
16pub fn parse(input: &str) -> Input {
17 let input = input.trim().as_bytes();
18
19 let mut part_one = 0;
20 let mut part_two = 0;
21 let mut hash = 0;
22 let mut label = 0;
23 let mut boxes: [Vec<Item>; 256] = from_fn(|_| Vec::new());
24
25 for (i, &b) in input.iter().enumerate() {
26 match b {
27 b',' => {
28 part_one += hash;
29 hash = 0;
30 label = 0;
31 continue;
32 }
33 b'-' => boxes[hash].retain(|item| item.label != label),
34 b'=' => {
35 let lens = input[i + 1].to_decimal();
36 let slot = &mut boxes[hash];
37
38 match slot.iter_mut().find(|item| item.label == label) {
39 Some(item) => item.lens = lens,
40 None => slot.push(Item { label, lens }),
41 }
42 }
43 _ => (),
44 }
45
46 let u = usize::from(b);
47 hash = ((hash + u) * 17) & 0xff;
48 label = (label << 8) | u;
49 }
50
51 for (i, next) in boxes.iter().enumerate() {
52 for (j, item) in next.iter().enumerate() {
53 part_two += (i + 1) * (j + 1) * item.lens;
54 }
55 }
56
57 (part_one + hash, part_two)
59}
60
61pub fn part1(input: &Input) -> usize {
62 input.0
63}
64
65pub fn part2(input: &Input) -> usize {
66 input.1
67}