1use crate::util::hash::*;
8
9type Input<'a> = (&'a str, Vec<(&'a str, &'a str)>);
10
11pub fn parse(input: &str) -> Input<'_> {
12 let (replacements, molecule) = input.rsplit_once("\n\n").unwrap();
13 (molecule, replacements.lines().map(|line| line.split_once(" => ").unwrap()).collect())
14}
15
16pub fn part1(input: &Input<'_>) -> usize {
17 let (molecule, replacements) = input;
18 let mut distinct = FastSet::new();
19
20 for (from, to) in replacements {
21 for (start, _) in molecule.match_indices(from) {
22 let size = molecule.len() - from.len() + to.len();
23 let end = start + from.len();
24
25 let mut string = String::with_capacity(size);
26 string.push_str(&molecule[..start]);
27 string.push_str(to);
28 string.push_str(&molecule[end..]);
29
30 distinct.insert(string);
31 }
32 }
33
34 distinct.len()
35}
36
37pub fn part2(input: &Input<'_>) -> usize {
38 let (molecule, _) = input;
39
40 let elements = molecule.chars().filter(char::is_ascii_uppercase).count();
41 let rn = molecule.matches("Rn").count();
42 let ar = molecule.matches("Ar").count();
43 let y = molecule.matches('Y').count();
44
45 elements - ar - rn - 2 * y - 1
46}