1use utils::bit::BitIterator;
2use utils::prelude::*;
3
4#[derive(Clone, Debug)]
6pub struct Day24 {
7 part1: u32,
8 part2: u32,
9}
10
11impl Day24 {
12 pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
13 let mut components: Vec<[u32; 2]> = parser::number_range(0..=63)
14 .repeat_n(b'/')
15 .parse_lines(input)?;
16 if components.len() >= 64 {
17 return Err(InputError::new(input, input.len(), "too many components"));
18 }
19
20 components.sort_unstable_by_key(|&[a, b]| a != b);
22
23 let mut bitsets = [0u64; 64];
24 let mut sums = [0u32; 64];
25 for (i, &[a, b]) in components.iter().enumerate() {
26 bitsets[a as usize] |= 1 << i;
27 bitsets[b as usize] |= 1 << i;
28 sums[i] = a + b;
29 }
30 if bitsets[0] == 0 {
31 return Err(InputError::new(input, 0, "no zero pin components"));
32 }
33
34 let mut out = [0u32; 64];
35 Self::search(&bitsets, &sums, &mut out, 0, 0, 0, 0);
36
37 Ok(Self {
38 part1: out.iter().max().copied().unwrap(),
39 part2: out.iter().rfind(|&&s| s > 0).copied().unwrap(),
40 })
41 }
42
43 fn search(
44 bitsets: &[u64],
45 sum: &[u32],
46 best: &mut [u32],
47 pins: u32,
48 used: u64,
49 strength: u32,
50 length: usize,
51 ) {
52 let remaining = bitsets[pins as usize] & !used;
53 if remaining == 0 {
54 best[length] = best[length].max(strength);
55 return;
56 }
57
58 for (component_index, component_bit) in BitIterator::ones(remaining) {
59 let component_sum = sum[component_index as usize];
60
61 Self::search(
62 bitsets,
63 sum,
64 best,
65 component_sum - pins,
66 used | component_bit,
67 strength + component_sum,
68 length + 1,
69 );
70
71 if component_sum == pins * 2 {
73 break;
74 }
75 }
76 }
77
78 #[must_use]
79 pub fn part1(&self) -> u32 {
80 self.part1
81 }
82
83 #[must_use]
84 pub fn part2(&self) -> u32 {
85 self.part2
86 }
87}
88
89examples!(Day24 -> (u32, u32) [
90 {input: "0/2\n2/2\n2/3\n3/4\n3/5\n0/1\n10/1\n9/10", part1: 31, part2: 19},
91]);