diff --git a/aoc2021/input/day14.txt b/aoc2021/input/day14.txt deleted file mode 100644 index eed6b77..0000000 --- a/aoc2021/input/day14.txt +++ /dev/null @@ -1,102 +0,0 @@ -CKFFSCFSCBCKBPBCSPKP - -NS -> P -KV -> B -FV -> S -BB -> V -CF -> O -CK -> N -BC -> B -PV -> N -KO -> C -CO -> O -HP -> P -HO -> P -OV -> O -VO -> C -SP -> P -BV -> H -CB -> F -SF -> H -ON -> O -KK -> V -HC -> N -FH -> P -OO -> P -VC -> F -VP -> N -FO -> F -CP -> C -SV -> S -PF -> O -OF -> H -BN -> V -SC -> V -SB -> O -NC -> P -CN -> K -BP -> O -PC -> H -PS -> C -NB -> K -VB -> P -HS -> V -BO -> K -NV -> B -PK -> K -SN -> H -OB -> C -BK -> S -KH -> P -BS -> S -HV -> O -FN -> F -FS -> N -FP -> F -PO -> B -NP -> O -FF -> H -PN -> K -HF -> H -VK -> K -NF -> K -PP -> H -PH -> B -SK -> P -HN -> B -VS -> V -VN -> N -KB -> O -KC -> O -KP -> C -OS -> O -SO -> O -VH -> C -OK -> B -HH -> B -OC -> P -CV -> N -SH -> O -HK -> N -NO -> F -VF -> S -NN -> O -FK -> V -HB -> O -SS -> O -FB -> B -KS -> O -CC -> S -KF -> V -VV -> S -OP -> H -KN -> F -CS -> H -CH -> P -BF -> F -NH -> O -NK -> C -OH -> C -BH -> O -FC -> V -PB -> B diff --git a/aoc2021/input/day14_provided.txt b/aoc2021/input/day14_provided.txt deleted file mode 100644 index b5594dd..0000000 --- a/aoc2021/input/day14_provided.txt +++ /dev/null @@ -1,18 +0,0 @@ -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/aoc2021/src/day14.rs b/aoc2021/src/day14.rs deleted file mode 100644 index c1ef925..0000000 --- a/aoc2021/src/day14.rs +++ /dev/null @@ -1,174 +0,0 @@ -use std::collections::{HashMap, HashSet, LinkedList}; -use std::fmt::Write; - -use anyhow::{Context, Result}; - -const INPUT: &str = include_str!("../input/day14.txt"); - -pub fn run() -> Result { - let mut res = String::with_capacity(128); - - writeln!(res, "part 1: {}", part1(INPUT)?)?; - - Ok(res) -} - -fn part1(input: &str) -> Result { - let (polymer, rules) = input.split_once("\n\n").context("couldn't split input")?; - let mut polymer: Polymer = polymer.parse()?; - let rules: Rules = rules.parse()?; - - let mut molecule_set = polymer.molecule_set(); - rules.0.values().for_each(|v| { - molecule_set.insert(*v); - }); - - for _ in 0..10 { - polymer.insert_pairs(&rules.0)?; - } - - let occurrences = polymer.compute_occurrences(&molecule_set); - - let (_, least_common_occurrences) = occurrences - .iter() - .min_by_key(|(_, occurrences)| occurrences) - .unwrap(); - let (_, most_common_occurrences) = occurrences - .iter() - .max_by_key(|(_, occurrences)| occurrences) - .unwrap(); - - Ok(most_common_occurrences - least_common_occurrences) -} - -struct Rules(HashMap<(char, char), char>); - -impl std::str::FromStr for Rules { - type Err = anyhow::Error; - - fn from_str(s: &str) -> Result { - Ok(Self( - s.lines() - .map(str::trim) - .map(|l| { - let (pair, res) = l.split_once(" -> ").context("couldn't parse rule")?; - Ok(( - ( - pair.chars().next().context("")?, - pair.chars().nth(1).context("")?, - ), - res.chars().next().context("couldn't parse rule")?, - )) - }) - .collect::>()?, - )) - } -} - -#[derive(Debug)] -struct Polymer { - molecules: Option>, -} - -impl Polymer { - fn insert_pairs(&mut self, rules: &HashMap<(char, char), char>) -> Result<()> { - debug_assert!(self.molecules.is_some()); - - self.molecules = Some(insert_pairs( - std::mem::replace(&mut self.molecules, None).unwrap(), - rules, - )?); - Ok(()) - } - - fn compute_occurrences(&self, molecule_set: &HashSet) -> Vec<(char, usize)> { - debug_assert!(self.molecules.is_some()); - - let mut res = Vec::new(); - for molecule in molecule_set { - let count = self - .molecules - .as_ref() - .unwrap() // we always have a Some, Option only used for std::mem::replace - .iter() - .filter(|&m| m == molecule) - .count(); - res.push((*molecule, count)); - } - - res - } - - fn molecule_set(&self) -> HashSet { - debug_assert!(self.molecules.is_some()); - - self.molecules.as_ref().unwrap().iter().copied().collect() - } -} - -impl std::str::FromStr for Polymer { - type Err = anyhow::Error; - - fn from_str(s: &str) -> Result { - let molecules = s.trim().chars().collect(); - - Ok(Polymer { - molecules: Some(molecules), - }) - } -} - -fn insert_pairs( - molecules: LinkedList, - rules: &HashMap<(char, char), char>, -) -> Result> { - if molecules.len() <= 1 { - return Ok(molecules); - } - - let mut head = molecules; - let mut tail = head.split_off(0); - - while tail.len() > 1 { - // List length is at least 2 - let mut iter = tail.iter(); - let (left, right) = (*iter.next().unwrap(), *iter.next().unwrap()); - - let to_insert = *rules - .get(&(left, right)) - .with_context(|| format!("couldn't find rule for pair ({}, {})", left, right))?; - - // tail = left - // new_tail = right -> rest - let new_tail = tail.split_off(1); - - // head = head -> left - head.append(&mut tail); - // head = head -> left -> to_insert - head.push_back(to_insert); - - // tail = right -> rest - tail = new_tail; - } - - head.append(&mut tail); - - Ok(head) -} - -#[cfg(test)] -mod tests { - use super::*; - - const PROVIDED: &str = include_str!("../input/day14_provided.txt"); - - #[test] - fn part1_provided() { - assert_eq!(part1(PROVIDED).unwrap(), 1588); - } - - #[test] - fn part1_real() { - assert_eq!(part1(INPUT).unwrap(), 3247); - } -} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index 4b6855a..cc37626 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -13,4 +13,3 @@ pub mod day10; pub mod day11; pub mod day12; pub mod day13; -pub mod day14; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index 0c06f85..1fa15e3 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -15,7 +15,6 @@ use aoc2021::day10; use aoc2021::day11; use aoc2021::day12; use aoc2021::day13; -use aoc2021::day14; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -32,7 +31,6 @@ fn main() -> Result<()> { day11::run, day12::run, day13::run, - day14::run, ]; aoc::run(days)