1use std::array::from_fn;
5
6use crate::util::parse::*;
7
8type Input = (usize, usize);
9
10struct Item<'a> {
11 label: &'a [u8],
12 lens: usize,
13}
14
15pub fn parse(input: &str) -> Input {
16 let mut part_one = 0;
17 let mut part_two = 0;
18 let mut boxes: [Vec<Item<'_>>; 256] = from_fn(|_| Vec::new());
19
20 for step in input.trim().as_bytes().split(|&b| b == b',') {
21 part_one += hash(step);
22 let (&last, rest) = step.split_last().unwrap();
23
24 if last == b'-' {
25 boxes[hash(rest)].retain(|item| item.label != rest);
27 } else {
28 let label = &rest[..rest.len() - 1];
29 let slot = &mut boxes[hash(label)];
30 let lens = last.to_decimal();
31
32 if let Some(i) = slot.iter().position(|item| item.label == label) {
34 slot[i].lens = lens;
35 } else {
36 slot.push(Item { label, lens });
37 }
38 }
39 }
40
41 for (i, next) in boxes.iter().enumerate() {
42 for (j, item) in next.iter().enumerate() {
43 part_two += (i + 1) * (j + 1) * item.lens;
44 }
45 }
46
47 (part_one, part_two)
48}
49
50pub fn part1(input: &Input) -> usize {
51 input.0
52}
53
54pub fn part2(input: &Input) -> usize {
55 input.1
56}
57
58#[inline]
60fn hash(slice: &[u8]) -> usize {
61 slice.iter().fold(0, |acc, &b| ((acc + b as usize) * 17) & 0xff)
62}