mod model; mod parsing; use aoc_runner_derive::{aoc, aoc_generator}; use itertools::Itertools; pub use model::{Input, Polymer, Rule, Rules}; pub use parsing::parse_input as parse_input_tokens; use yap::IntoTokens; #[aoc_generator(day14)] pub fn parse_input(input: &str) -> Input { parse_input_tokens(&mut input.into_tokens()).unwrap() } #[aoc(day14, part1)] pub fn part1(input: &Input) -> usize { solve(input, 10) } pub fn solve(Input { polymer, rules }: &Input, iterations: usize) -> usize { let mut polymer = polymer.clone(); for _ in 0..iterations { polymer.apply(rules) } let counts: Vec<(char, usize)> = polymer .element_counts() .iter() .sorted_by(|a, b| Ord::cmp(&b.1, &a.1)) .map(|(element, count)| (*element, *count)) .collect(); counts.first().unwrap().1 - counts.last().unwrap().1 } #[aoc(day14, part2)] pub fn part2(input: &Input) -> usize { solve(input, 40) } #[cfg(test)] mod test { const EXAMPLE_INPUT: &str = "NNCB CH -> B HH -> N CB -> H NH -> C HB -> C HC -> B HN -> C NN -> C BH -> H NC -> B NB -> B BN -> B BB -> N BC -> B CC -> N CN -> C"; const RESULT_PART_1: usize = 1588; const RESULT_PART_2: usize = 2188189693529; #[test] fn part1_example() { let result = super::part1(&super::parse_input(EXAMPLE_INPUT)); assert_eq!(result, RESULT_PART_1); } #[test] fn part2_example() { let result = super::part2(&super::parse_input(EXAMPLE_INPUT)); assert_eq!(result, RESULT_PART_2); } #[test] fn parse_example() { let _example = super::parse_input(EXAMPLE_INPUT); } }