80 lines
1.6 KiB
Rust
80 lines
1.6 KiB
Rust
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);
|
|
}
|
|
}
|