aoc/year2015/
day19.rs

1//! # Medicine for Rudolph
2//!
3//! Part one is a brute force search and replace of every possibility.
4//!
5//! Part two uses the analysis from `askalski` provided on the
6//! [Day 19 solution megathread](https://www.reddit.com/r/adventofcode/comments/3xflz8/day_19_solutions/).
7use 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}