advent-of-code 2025.5.0

Solutions to Advent of Code
Documentation
use crate::common::parser::parse_lines;
use crate::input::Input;

pub fn solve(input: &Input) -> Result<u32, String> {
    const TARGET_SIZE: u8 = 150;

    let container_sizes = parse_lines::<u8>(input.text)?;

    if input.is_part_one() {
        let mut answers = vec![0; (TARGET_SIZE + 1) as usize];
        answers[0] = 1;
        for container_size in container_sizes {
            for next_size in (container_size..=TARGET_SIZE).rev() {
                answers[next_size as usize] += answers[(next_size - container_size) as usize];
            }
        }
        Ok(answers[TARGET_SIZE as usize])
    } else {
        let all_bits = u32::MAX >> (32 - container_sizes.len());

        for containers_to_use in 1..=container_sizes.len() {
            let possible_combinations = (1..=all_bits)
                .filter(|bit_mask| {
                    if bit_mask.count_ones() != containers_to_use as u32 {
                        return false;
                    }
                    let total_size: u32 = container_sizes
                        .iter()
                        .enumerate()
                        .filter_map(|(idx, &size)| {
                            (((1 << idx) & bit_mask) != 0).then_some(u32::from(size))
                        })
                        .sum();
                    total_size == u32::from(TARGET_SIZE)
                })
                .count();
            if possible_combinations != 0 {
                return Ok(possible_combinations as u32);
            }
        }

        Err("No solution found".to_string())
    }
}

#[test]
pub fn tests() {
    let real_input = include_str!("day17_input.txt");
    test_part_one!(real_input => 1304);
    test_part_two!(real_input => 18);
}