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