advent_of_code/year2015/
day24.rs1use crate::common::parser::parse_lines;
2use crate::input::Input;
3
4fn visit_subset_internal<F>(
10 input: &[u8],
11 output: &mut [u8],
12 input_idx: usize,
13 output_idx: usize,
14 on_subset: &mut F,
15) where
16 F: FnMut(&[u8]),
17{
18 if output_idx == output.len() {
19 on_subset(output);
20 return;
21 } else if input_idx >= input.len() {
22 return;
23 }
24
25 output[output_idx] = input[input_idx];
27 visit_subset_internal(input, output, input_idx + 1, output_idx + 1, on_subset);
28 visit_subset_internal(input, output, input_idx + 1, output_idx, on_subset);
30}
31
32fn visit_subsets<F>(input: &[u8], subset_size: usize, on_subsete: &mut F)
33where
34 F: FnMut(&[u8]),
35{
36 let mut output = vec![0; subset_size];
37 visit_subset_internal(input, &mut output, 0, 0, on_subsete);
38}
39
40pub fn solve(input: &Input) -> Result<u128, String> {
41 let weights = parse_lines::<u8>(input.text)?;
42
43 let sum: u32 = weights.iter().map(|&w| u32::from(w)).sum();
44 let group_weight = sum / input.part_values(3, 4);
45
46 for subset_size in 1..weights.len() {
47 let mut result = None;
48 visit_subsets(&weights, subset_size, &mut |subset: &[u8]| {
49 if subset.iter().map(|&w| u32::from(w)).sum::<u32>() == group_weight {
50 let product = subset.iter().map(|&w| u128::from(w)).product();
51 if product < result.unwrap_or(u128::MAX) {
52 result = Some(product);
53 }
54 }
55 });
56 if let Some(product) = result {
57 return Ok(product);
58 }
59 }
60
61 Err("No solution found".to_string())
62}
63
64#[test]
65pub fn tests() {
66 let real_input = include_str!("day24_input.txt");
67 test_part_one!(real_input => 10_723_906_903);
68 test_part_two!(real_input => 74_850_409);
69}