1use utils::prelude::*;
2
3#[derive(Clone, Debug)]
5pub struct Day17 {
6 part1: u16,
7 part2: u16,
8}
9
10impl Day17 {
11 pub fn new(input: &str, input_type: InputType) -> Result<Self, InputError> {
12 let parsed = parser::u8().parse_lines(input)?;
13 let (part1, part2) = match input_type {
14 InputType::Example => Self::calculate::<25>(&parsed),
15 InputType::Real => Self::calculate::<150>(&parsed),
16 };
17 Ok(Self { part1, part2 })
18 }
19
20 fn calculate<const N: usize>(sizes: &[u8]) -> (u16, u16) {
21 let mut matrix = vec![[0; N]; sizes.len()];
23
24 for (i, size) in sizes.iter().copied().enumerate() {
25 for containers in (1..=i).rev() {
27 for total in 0..N - size as usize {
28 matrix[containers][total + size as usize] += matrix[containers - 1][total];
29 }
30 }
31 matrix[0][size as usize - 1] += 1;
32 }
33
34 (
35 matrix.iter().map(|x| x[N - 1]).sum(),
36 matrix
37 .iter()
38 .map(|x| x[N - 1])
39 .find(|&x| x > 0)
40 .unwrap_or(0),
41 )
42 }
43
44 #[must_use]
45 pub fn part1(&self) -> u16 {
46 self.part1
47 }
48
49 #[must_use]
50 pub fn part2(&self) -> u16 {
51 self.part2
52 }
53}
54
55examples!(Day17 -> (u16, u16) [
56 {input: "20\n15\n10\n5\n5", part1: 4, part2: 3},
57]);