From c081f2287cc18513e69603e500f5dfbe9ee62cf8 Mon Sep 17 00:00:00 2001 From: Lars Martens Date: Tue, 14 Dec 2021 17:57:04 +0100 Subject: [PATCH] Day 14 --- input/14-test.txt | 18 +++++++ input/14.txt | 102 ++++++++++++++++++++++++++++++++++++++++ src/bin/14.rs | 117 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+) create mode 100644 input/14-test.txt create mode 100644 input/14.txt create mode 100644 src/bin/14.rs diff --git a/input/14-test.txt b/input/14-test.txt new file mode 100644 index 0000000..b5594dd --- /dev/null +++ b/input/14-test.txt @@ -0,0 +1,18 @@ +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 diff --git a/input/14.txt b/input/14.txt new file mode 100644 index 0000000..0400f1a --- /dev/null +++ b/input/14.txt @@ -0,0 +1,102 @@ +NCOPHKVONVPNSKSHBNPF + +ON -> C +CK -> H +HC -> B +NP -> S +NH -> H +CB -> C +BB -> H +BC -> H +NN -> C +OH -> B +SF -> V +PB -> H +CP -> P +BN -> O +NB -> B +KB -> P +PV -> F +SH -> V +KP -> S +OF -> K +BS -> V +PF -> O +BK -> S +FB -> B +SV -> B +BH -> V +VK -> N +CS -> V +FV -> F +HS -> C +KK -> O +SP -> N +FK -> B +CF -> C +HP -> F +BF -> O +KC -> C +VP -> O +BP -> P +FF -> V +NO -> C +HK -> C +HV -> B +PK -> P +OV -> F +VN -> H +PC -> K +SB -> H +VO -> V +BV -> K +NC -> H +OB -> S +SN -> B +HF -> P +VF -> B +HN -> H +KS -> S +SC -> S +CV -> B +NS -> P +KO -> V +FS -> O +PH -> K +BO -> C +FH -> B +CO -> O +FO -> F +VV -> N +CH -> V +NK -> N +PO -> K +OK -> K +PP -> O +OC -> P +FC -> N +VH -> S +PN -> C +VB -> C +VS -> P +HO -> F +OP -> S +HB -> N +CC -> K +KN -> S +SK -> C +OS -> N +KH -> B +FP -> S +NF -> S +CN -> S +KF -> C +SS -> C +SO -> S +NV -> O +FN -> B +PS -> S +HH -> C +VC -> S +OO -> C +KV -> P diff --git a/src/bin/14.rs b/src/bin/14.rs new file mode 100644 index 0000000..747fcb1 --- /dev/null +++ b/src/bin/14.rs @@ -0,0 +1,117 @@ +use std::{collections::HashMap, hash::Hash}; + +fn main() { + let mut puzzle = input(); + for _ in 0..10 { + puzzle.step(); + } + println!("First solution: {}", puzzle.score()); + for _ in 0..30 { + puzzle.step(); + } + println!("Second solution: {}", puzzle.score()); +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +struct Digram(char, char); + +#[derive(Debug)] +struct Puzzle { + /// polymer is a count of all digrams in it. + polymer: HashMap, + /// start and end need to be kept track of, since all other chars are counted doubly, + /// due to the nature of counting the digrams. + start: char, + end: char, + instructions: Vec, +} + +/// ab -> to +#[derive(Debug, Clone, Copy)] +struct Instruction { + from: Digram, + to: char, +} + +impl Puzzle { + fn step(&mut self) { + let mut new_polymer = HashMap::new(); + for (&old_digram, &count) in &self.polymer { + if let Some(i) = self.find_instruction(old_digram) { + for new_digram in i.output() { + let counter = new_polymer.entry(new_digram).or_default(); + *counter += count; + } + } else { + let counter = new_polymer.entry(old_digram).or_default(); + *counter += count; + } + } + self.polymer = new_polymer; + } + + fn find_instruction(&self, d: Digram) -> Option { + self.instructions.iter().copied().find(|i| i.from == d) + } + + fn score(&self) -> usize { + // All chars were counted doubly, due to the nature of the digrams, except start and end. + // Add one for those manually here. + let mut char_count: HashMap = + [(self.start, 1), (self.end, 1)].into_iter().collect(); + + for (&d, &count) in &self.polymer { + for c in [d.0, d.1] { + let counter = char_count.entry(c).or_default(); + *counter += count; + } + } + + let mut doubly_counted: Vec = char_count.values().copied().collect(); + doubly_counted.sort_unstable(); + + (doubly_counted.last().unwrap() - doubly_counted.first().unwrap()) / 2 + } +} + +impl Instruction { + fn output(&self) -> [Digram; 2] { + [Digram(self.from.0, self.to), Digram(self.to, self.from.1)] + } +} + +fn input() -> Puzzle { + let file = include_str!("../../input/14.txt"); + + let polymer_chars: Vec = file.lines().next().unwrap().trim().chars().collect(); + let polymer = polymer_chars + .windows(2) + .into_iter() + .map(|w| Digram(w[0], w[1])) + .fold(HashMap::new(), |mut acc, d| { + let count = acc.entry(d).or_default(); + *count += 1; + acc + }); + + let instructions = file + .lines() + .filter(|l| l.contains("->")) + .filter_map(|l| l.split_once(" -> ")) + .map(|(from, to)| { + let a = from.chars().next().unwrap(); + let b = from.chars().nth(1).unwrap(); + Instruction { + from: Digram(a, b), + to: to.chars().next().unwrap(), + } + }) + .collect(); + + Puzzle { + polymer, + instructions, + start: polymer_chars.first().copied().unwrap(), + end: polymer_chars.last().copied().unwrap(), + } +}