diff --git a/input/14.txt b/input/14.txt new file mode 100644 index 0000000..eb79acf --- /dev/null +++ b/input/14.txt @@ -0,0 +1,102 @@ +BVBNBVPOKVFHBVCSHCFO + +SO -> V +PB -> P +HV -> N +VF -> O +KS -> F +BB -> C +SH -> H +SB -> C +FS -> F +PV -> F +BC -> K +SF -> S +NO -> O +SK -> C +PO -> N +VK -> F +FC -> C +VV -> S +SV -> S +HH -> K +FH -> K +HN -> O +NP -> F +PK -> N +VO -> K +NC -> C +KP -> B +CS -> C +KO -> F +BK -> N +OO -> N +CF -> H +KN -> C +BV -> S +OK -> O +CN -> F +OP -> O +VP -> N +OC -> P +NH -> C +VN -> S +VC -> B +NF -> H +FO -> H +CC -> B +KB -> N +CP -> N +HK -> N +FB -> H +BH -> V +BN -> N +KC -> F +CV -> K +SP -> V +VS -> P +KF -> S +CH -> V +NS -> N +HS -> O +CK -> K +NB -> O +OF -> K +VB -> N +PS -> B +KH -> P +BS -> C +VH -> C +KK -> F +FN -> F +BP -> B +HF -> O +HB -> V +OV -> H +NV -> N +HO -> S +OS -> H +SS -> K +BO -> V +OB -> K +HP -> P +CO -> B +PP -> K +HC -> N +BF -> S +NK -> S +ON -> P +PH -> C +FV -> H +CB -> H +PC -> K +FF -> P +PN -> P +NN -> O +PF -> F +SC -> C +FK -> K +SN -> K +KV -> P +FP -> B +OH -> F diff --git a/src/day14.rs b/src/day14.rs new file mode 100644 index 0000000..99ecde0 --- /dev/null +++ b/src/day14.rs @@ -0,0 +1,88 @@ +use std::collections::HashMap; + +pub struct InsertionRule([char; 2], char); + +pub struct InputData { + polymer_template: String, + rules: Vec +} + +fn parse_rule(line: &str) -> InsertionRule { + let (pattern, expansion) = line.split_once(" -> ").unwrap(); + return InsertionRule( + [pattern.chars().nth(0).unwrap(), pattern.chars().nth(1).unwrap()], + expansion.chars().nth(0).unwrap() + ); +} + +pub fn parse_input(input: &str) -> InputData { + let (polymer_template, rules_section) = input.split_once("\n\n").unwrap(); + let rules = rules_section.lines() + .map(parse_rule) + .collect(); + return InputData { + polymer_template: polymer_template.into(), + rules + }; +} + +fn expand_polymer(polymer: Vec, rules: &Vec) -> Vec { + let mut new_polymer = Vec::new(); + for i in 0..polymer.len()-1 { + new_polymer.push(polymer[i]); + for rule in rules { + if rule.0[0] == polymer[i] && rule.0[1] == polymer[i+1] { + new_polymer.push(rule.1); + } + } + } + new_polymer.push(*polymer.last().unwrap()); + return new_polymer; +} + +pub fn part1(input: &InputData) -> u32 { + let mut polymer = input.polymer_template.chars().collect(); + for _ in 0..10 { + polymer = expand_polymer(polymer, &input.rules); + } + + let mut element_amounts = HashMap::new(); + for c in polymer { + let amount = element_amounts.entry(c).or_insert(0); + *amount += 1; + } + + let least_common_element = element_amounts.iter().min_by(|a, b| a.1.cmp(b.1)).unwrap().1; + let most_common_element = element_amounts.iter().max_by(|a, b| a.1.cmp(b.1)).unwrap().1; + return most_common_element - least_common_element; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_example() { + let polymer_template = String::from("NNCB"); + let rules = vec![ + InsertionRule(['C', 'H'], 'B'), + InsertionRule(['H', 'H'], 'N'), + InsertionRule(['C', 'B'], 'H'), + InsertionRule(['N', 'H'], 'C'), + InsertionRule(['H', 'B'], 'C'), + InsertionRule(['H', 'C'], 'B'), + InsertionRule(['H', 'N'], 'C'), + InsertionRule(['N', 'N'], 'C'), + InsertionRule(['B', 'H'], 'H'), + InsertionRule(['N', 'C'], 'B'), + InsertionRule(['N', 'B'], 'B'), + InsertionRule(['B', 'N'], 'B'), + InsertionRule(['B', 'B'], 'N'), + InsertionRule(['B', 'C'], 'B'), + InsertionRule(['C', 'C'], 'N'), + InsertionRule(['C', 'N'], 'C') + ]; + let result = part1(&InputData { polymer_template, rules }); + assert_eq!(result, 1588); + } +} diff --git a/src/main.rs b/src/main.rs index 73e0257..4a95005 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ mod day10; mod day11; mod day12; mod day13; +mod day14; use std::{env, process}; use std::fs::File; @@ -53,6 +54,7 @@ fn run(day: i32, part: i32, input_filename: &str) { "12.2" => println!("{}", day12::part2(&day12::parse_input(&contents))), "13.1" => println!("{}", day13::part1(&day13::parse_input(&contents))), "13.2" => day13::part2(&day13::parse_input(&contents)), + "14.1" => println!("{}", day14::part1(&day14::parse_input(&contents))), _ => println!("Day {} part {} not found", day, part) } }