advent-of-code 2022.0.46

Solutions to Advent of Code
Documentation
use crate::input::Input;
use crate::year2017::disjoint_set::DisjointSet;

pub fn solve(input: &Input) -> Result<usize, String> {
    let num_programs = input.text.lines().count();
    let mut program_groups = DisjointSet::new(num_programs);

    for (line_index, line) in input.text.lines().enumerate() {
        let error_message = || {
            format!(
                "Invalid input at line {}: Expected 'ID <-> ID[, ID]'",
                line_index + 1
            )
        };
        let parts = line.split(" <-> ").collect::<Vec<_>>();
        if parts.len() != 2 {
            return Err(error_message());
        }
        let first = parts[0].parse::<usize>().map_err(|_| error_message())?;
        for other_str in parts[1].split(", ") {
            let other = other_str.parse::<usize>().map_err(|_| error_message())?;
            program_groups.join(first, other);
        }
    }

    Ok(if input.is_part_one() {
        program_groups.size(0)
    } else {
        program_groups.num_groups()
    })
}

#[test]
fn tests() {
    use crate::input::{test_part_one, test_part_two};

    test_part_one!(
            "0 <-> 2
1 <-> 1
2 <-> 0, 3, 4
3 <-> 2, 4
4 <-> 2, 3, 6
5 <-> 6
6 <-> 4, 5"
        => 6
    );

    let real_input = include_str!("day12_input.txt");
    test_part_one!(real_input => 152);
    test_part_two!(real_input => 186);
}