Solve day 14!
This commit is contained in:
parent
0eaa4648f0
commit
32008c4408
|
@ -0,0 +1,97 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use color_eyre::{eyre::eyre, Result};
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
type PairMap = HashMap<(char, char), char>;
|
||||||
|
type PairCounts = HashMap<(char, char), isize>;
|
||||||
|
|
||||||
|
pub fn solve() -> Result<()> {
|
||||||
|
let input_data = include_str!("../../data/day_14.txt").trim();
|
||||||
|
println!("Day 14 Part 1: {}", part_1(input_data)?);
|
||||||
|
println!("Day 14 Part 2: {}", part_2(input_data)?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(input: &str) -> Result<(String, PairMap)> {
|
||||||
|
let mut lines = input.lines();
|
||||||
|
let template = lines
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| eyre!("Invalid input: {}", input))?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let mut pairs = HashMap::new();
|
||||||
|
|
||||||
|
for line in lines.skip(1) {
|
||||||
|
let (a, b, c) = line
|
||||||
|
.replace(" -> ", "")
|
||||||
|
.chars()
|
||||||
|
.collect_tuple()
|
||||||
|
.ok_or_else(|| eyre!("Invalid line: {}", line))?;
|
||||||
|
|
||||||
|
pairs.insert((a, b), c);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((template, pairs))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(counts: &PairCounts, pairs: &PairMap) -> PairCounts {
|
||||||
|
let mut to_add = PairCounts::new();
|
||||||
|
|
||||||
|
for (pair, count) in counts {
|
||||||
|
if let Some(character) = pairs.get(pair) {
|
||||||
|
*to_add.entry((pair.0, *character)).or_default() += count;
|
||||||
|
*to_add.entry((*character, pair.1)).or_default() += count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
to_add
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count_totals(counts: &PairCounts) -> HashMap<char, isize> {
|
||||||
|
let mut totals = HashMap::new();
|
||||||
|
|
||||||
|
for ((_, b), count) in counts {
|
||||||
|
// If I count the first character in the pair the end result ends up being
|
||||||
|
// off by one...?
|
||||||
|
*totals.entry(*b).or_default() += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
totals
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(input: &str, steps: isize) -> Result<isize> {
|
||||||
|
let (template, pairs) = parse(input)?;
|
||||||
|
|
||||||
|
let mut counts = PairCounts::new();
|
||||||
|
for (a, b) in template.chars().tuple_windows() {
|
||||||
|
*counts.entry((a, b)).or_default() += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for _ in 0..steps {
|
||||||
|
counts = apply(&counts, &pairs);
|
||||||
|
}
|
||||||
|
|
||||||
|
let totals = count_totals(&counts)
|
||||||
|
.into_iter()
|
||||||
|
.sorted_by(|(_, a), (_, b)| a.cmp(b));
|
||||||
|
|
||||||
|
let (_, min) = totals
|
||||||
|
.clone()
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| eyre!("No minimum found"))?;
|
||||||
|
let (_, max) = totals
|
||||||
|
.clone()
|
||||||
|
.last()
|
||||||
|
.ok_or_else(|| eyre!("No maximum found"))?;
|
||||||
|
|
||||||
|
Ok(max - min)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part_1(input: &str) -> Result<isize> {
|
||||||
|
run(input, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part_2(input: &str) -> Result<isize> {
|
||||||
|
run(input, 40)
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ mod day_07;
|
||||||
mod day_08;
|
mod day_08;
|
||||||
mod day_09;
|
mod day_09;
|
||||||
mod day_10;
|
mod day_10;
|
||||||
|
mod day_14;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
color_eyre::install()?;
|
color_eyre::install()?;
|
||||||
|
@ -29,6 +30,7 @@ fn main() -> Result<()> {
|
||||||
day_08::solve,
|
day_08::solve,
|
||||||
day_09::solve,
|
day_09::solve,
|
||||||
day_10::solve,
|
day_10::solve,
|
||||||
|
day_14::solve,
|
||||||
];
|
];
|
||||||
|
|
||||||
for day in days {
|
for day in days {
|
||||||
|
|
Loading…
Reference in New Issue