1use utils::prelude::*;
2
3#[derive(Clone, Debug)]
5pub struct Day24 {
6 presents: Vec<u32>,
7 remaining_totals: Vec<u32>,
8 sum: u32,
9}
10
11impl Day24 {
12 pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
13 let mut presents = parser::u32().parse_lines(input)?;
14 presents.sort_unstable_by(|a, b| b.cmp(a));
15
16 let mut remaining_totals = presents
19 .iter()
20 .rev()
21 .scan(0, |acc, x| {
22 *acc += x;
23 Some(*acc)
24 })
25 .collect::<Vec<_>>();
26 remaining_totals.reverse();
27
28 let sum: u32 = remaining_totals.first().copied().unwrap_or(0);
29 if sum % 12 != 0 {
30 return Err(InputError::new(input, 0, "Total must be multiple of 12"));
31 }
32
33 Ok(Self {
34 presents,
35 remaining_totals,
36 sum,
37 })
38 }
39
40 #[must_use]
41 pub fn part1(&self) -> u64 {
42 let mut min = (u32::MAX, u64::MAX);
43 self.min_quantum_entanglement(self.sum / 3, 0, 0, 1, &mut min);
44 min.1
45 }
46
47 #[must_use]
48 pub fn part2(&self) -> u64 {
49 let mut min = (u32::MAX, u64::MAX);
50 self.min_quantum_entanglement(self.sum / 4, 0, 0, 1, &mut min);
51 min.1
52 }
53
54 fn min_quantum_entanglement(
55 &self,
56 remaining: u32,
57 start_index: usize,
58 count: u32,
59 product: u64,
60 min_found: &mut (u32, u64),
61 ) {
62 if remaining == 0 {
63 *min_found = (*min_found).min((count, product));
64 return;
65 }
66
67 if count >= min_found.0 {
69 return;
70 }
71
72 if self.remaining_totals.get(start_index).copied().unwrap_or(0) < remaining {
75 return;
76 }
77
78 for (i, &size) in self.presents[start_index..].iter().enumerate() {
79 if size <= remaining {
80 self.min_quantum_entanglement(
81 remaining - size,
82 start_index + i + 1,
83 count + 1,
84 product * u64::from(size),
85 min_found,
86 )
87 }
88 }
89 }
90}
91
92examples!(Day24 -> (u64, u64) [
93 {input: "1\n2\n3\n4\n5\n7\n8\n9\n10\n11", part1: 99, part2: 44},
94]);