diff options
author | Justin Wernick <justin@worthe-it.co.za> | 2021-12-15 21:26:26 +0200 |
---|---|---|
committer | Justin Wernick <justin@worthe-it.co.za> | 2021-12-15 21:26:26 +0200 |
commit | 5a4273eea2bb1e4149605f4f09e87ab9349c2ab7 (patch) | |
tree | acf22ef0d62db0a93f77edd8a8365783f03898d2 | |
parent | 828ba1c2409a320564ff448ce30b99566a030085 (diff) |
Day 14 part 1
-rw-r--r-- | inputs/day_14.txt | 102 | ||||
-rw-r--r-- | src/bin/day_14.rs | 98 |
2 files changed, 200 insertions, 0 deletions
diff --git a/inputs/day_14.txt b/inputs/day_14.txt new file mode 100644 index 0000000..e84aae5 --- /dev/null +++ b/inputs/day_14.txt @@ -0,0 +1,102 @@ +SNPVPFCPPKSBNSPSPSOF + +CF -> N +NK -> B +SF -> B +HV -> P +FN -> S +VV -> F +FO -> F +VN -> V +PV -> P +FF -> P +ON -> S +PB -> S +PK -> P +OO -> P +SP -> F +VF -> H +OV -> C +BN -> P +OH -> H +NC -> F +BH -> N +CS -> C +BC -> N +OF -> N +SN -> B +FP -> F +FV -> K +HP -> H +VB -> P +FH -> F +HF -> P +BB -> O +HH -> S +PC -> O +PP -> B +VS -> B +HC -> H +NS -> N +KF -> S +BO -> V +NP -> S +NF -> K +BS -> O +KK -> O +VC -> V +KP -> K +CK -> P +HN -> F +KN -> H +KH -> N +SB -> S +NO -> K +HK -> H +BF -> V +SV -> B +CV -> P +CO -> P +FC -> O +CP -> H +CC -> N +CN -> P +SK -> V +SS -> V +VH -> B +OS -> N +FB -> H +NB -> N +SC -> K +NV -> H +HO -> S +SO -> P +PH -> C +VO -> O +OB -> O +FK -> S +PN -> P +VK -> O +NH -> N +OC -> B +BP -> O +PF -> F +KB -> K +KV -> B +PO -> N +NN -> K +CH -> O +KC -> P +OP -> V +VP -> F +OK -> P +FS -> K +CB -> S +HB -> N +KS -> O +BK -> C +BV -> O +SH -> H +PS -> N +HS -> K +KO -> N diff --git a/src/bin/day_14.rs b/src/bin/day_14.rs new file mode 100644 index 0000000..c534b8c --- /dev/null +++ b/src/bin/day_14.rs @@ -0,0 +1,98 @@ +use nom::{ + bytes::complete::tag, + character::complete::{alpha1, anychar, line_ending}, + combinator::map, + multi::{many0, separated_list1}, + sequence::tuple, + IResult, +}; +use std::{collections::BTreeMap, fs}; + +fn main() -> Result<(), Box<dyn std::error::Error>> { + let input = fs::read_to_string("inputs/day_14.txt")?; + let mut polymer = parse_polymer_expansion(&input).unwrap().1; + for _ in 0..10 { + polymer.expand(); + } + dbg!(polymer.most_common_element_count() - polymer.least_common_element_count()); + for _ in 0..30 { + polymer.expand(); + } + dbg!(polymer.most_common_element_count() - polymer.least_common_element_count()); + + Ok(()) +} + +#[derive(Debug)] +struct PolymerExpansion { + polymer: Vec<char>, + rules: Rules, + element_counts: BTreeMap<char, u64>, +} + +impl PolymerExpansion { + fn new(polymer: Vec<char>, rules: Rules) -> PolymerExpansion { + let mut element_counts = BTreeMap::new(); + for c in &polymer { + *element_counts.entry(*c).or_insert(0) += 1; + } + + PolymerExpansion { + polymer, + rules, + element_counts, + } + } + + fn expand(&mut self) { + let mut next_polymer = Vec::new(); + for i in 0..self.polymer.len() - 1 { + next_polymer.push(self.polymer[i]); + if let Some(extra) = self.rules.get(&[self.polymer[i], self.polymer[i + 1]]) { + next_polymer.push(extra); + *self.element_counts.entry(extra).or_insert(0) += 1; + } + } + next_polymer.push(self.polymer[self.polymer.len() - 1]); + self.polymer = next_polymer; + } + + fn most_common_element_count(&self) -> u64 { + self.element_counts.values().max().cloned().unwrap_or(0) + } + + fn least_common_element_count(&self) -> u64 { + self.element_counts.values().min().cloned().unwrap_or(0) + } +} + +#[derive(Debug)] +struct Rules { + rules: BTreeMap<[char; 2], char>, +} + +impl Rules { + fn get(&self, key: &[char; 2]) -> Option<char> { + self.rules.get(key).cloned() + } +} + +fn parse_polymer_expansion(input: &str) -> IResult<&str, PolymerExpansion> { + let (input, polymer) = map(alpha1, |s: &str| s.chars().collect())(input)?; + let (input, _) = many0(line_ending)(input)?; + let (input, rules) = parse_rules(input)?; + Ok((input, PolymerExpansion::new(polymer, rules))) +} + +fn parse_rules(input: &str) -> IResult<&str, Rules> { + map(separated_list1(line_ending, parse_rule), |rules| Rules { + rules: rules.into_iter().collect(), + })(input) +} + +fn parse_rule(input: &str) -> IResult<&str, ([char; 2], char)> { + map( + tuple((anychar, anychar, tag(" -> "), anychar)), + |(p1, p2, _, r)| ([p1, p2], r), + )(input) +} |