Skip to main content

advent_of_code/year2018/
day05.rs

1use crate::input::Input;
2
3type PolymerUnit = u8;
4
5const fn destroys_each_other(a: PolymerUnit, b: PolymerUnit) -> bool {
6    a.eq_ignore_ascii_case(&b) && a != b
7}
8
9pub fn solve(input: &Input) -> Result<usize, String> {
10    let input_polymer = input.text.as_bytes();
11    let mut new_polymer = Vec::<PolymerUnit>::with_capacity(input_polymer.len());
12
13    let candidates_for_removal = input.part_values(0..=0, b'a'..=b'z');
14
15    candidates_for_removal
16        .map(|to_remove_lower| {
17            new_polymer.clear();
18
19            for &unit in input_polymer
20                .iter()
21                .filter(|unit| !unit.eq_ignore_ascii_case(&to_remove_lower))
22            {
23                let unit_reacts_with_last = new_polymer
24                    .last()
25                    .is_some_and(|&last| destroys_each_other(unit, last));
26
27                if unit_reacts_with_last {
28                    new_polymer.pop();
29                } else {
30                    new_polymer.push(unit);
31                }
32            }
33
34            new_polymer.len()
35        })
36        .min()
37        .ok_or_else(|| "Internal error".to_string())
38}
39
40#[test]
41fn tests() {
42    test_part_one!("aA"=>0);
43    test_part_one!("abBA" => 0);
44    test_part_one!("abAB" => 4);
45    test_part_one!("aabAAB" => 6);
46
47    test_part_two!("dabAcCaCBAcCcaDA" => 4);
48
49    let input = include_str!("day05_input.txt");
50    test_part_one!(input => 11252);
51    test_part_two!(input => 6118);
52}