feat: solve day 14 part 2
This commit is contained in:
parent
42ea48d4e9
commit
dccffe6ab1
148
src/day14.rs
148
src/day14.rs
@ -1,39 +1,34 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub struct InsertionRule([char; 2], char);
|
|
||||||
|
|
||||||
pub struct InputData {
|
pub struct InputData {
|
||||||
polymer_template: String,
|
polymer_template: String,
|
||||||
rules: Vec<InsertionRule>
|
rules: HashMap<[char; 2], char>
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
pub fn parse_input(input: &str) -> InputData {
|
||||||
let (polymer_template, rules_section) = input.split_once("\n\n").unwrap();
|
let (polymer_template, rules_section) = input.split_once("\n\n").unwrap();
|
||||||
let rules = rules_section.lines()
|
let mut rules = HashMap::new();
|
||||||
.map(parse_rule)
|
for line in rules_section.lines() {
|
||||||
.collect();
|
let (pattern, expansion) = line.split_once(" -> ").unwrap();
|
||||||
|
rules.insert(
|
||||||
|
[pattern.chars().nth(0).unwrap(), pattern.chars().nth(1).unwrap()],
|
||||||
|
expansion.chars().nth(0).unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
return InputData {
|
return InputData {
|
||||||
polymer_template: polymer_template.into(),
|
polymer_template: polymer_template.into(),
|
||||||
rules
|
rules
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_polymer(polymer: Vec<char>, rules: &Vec<InsertionRule>) -> Vec<char> {
|
fn naive_expand_polymer(polymer: Vec<char>, rules: &HashMap<[char; 2], char>) -> Vec<char> {
|
||||||
let mut new_polymer = Vec::new();
|
let mut new_polymer = Vec::new();
|
||||||
for i in 0..polymer.len()-1 {
|
for i in 0..polymer.len()-1 {
|
||||||
new_polymer.push(polymer[i]);
|
new_polymer.push(polymer[i]);
|
||||||
for rule in rules {
|
let pair = [polymer[i], polymer[i+1]];
|
||||||
if rule.0[0] == polymer[i] && rule.0[1] == polymer[i+1] {
|
let rule = rules.get(&pair);
|
||||||
new_polymer.push(rule.1);
|
if rule != None {
|
||||||
}
|
new_polymer.push(*rule.unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new_polymer.push(*polymer.last().unwrap());
|
new_polymer.push(*polymer.last().unwrap());
|
||||||
@ -43,7 +38,7 @@ fn expand_polymer(polymer: Vec<char>, rules: &Vec<InsertionRule>) -> Vec<char> {
|
|||||||
pub fn part1(input: &InputData) -> u32 {
|
pub fn part1(input: &InputData) -> u32 {
|
||||||
let mut polymer = input.polymer_template.chars().collect();
|
let mut polymer = input.polymer_template.chars().collect();
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
polymer = expand_polymer(polymer, &input.rules);
|
polymer = naive_expand_polymer(polymer, &input.rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut element_amounts = HashMap::new();
|
let mut element_amounts = HashMap::new();
|
||||||
@ -57,6 +52,58 @@ pub fn part1(input: &InputData) -> u32 {
|
|||||||
return most_common_element - least_common_element;
|
return most_common_element - least_common_element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expand_polymer(polymer_pairs: &HashMap<[char; 2], u64>, rules: &HashMap<[char; 2], char>) -> HashMap<[char; 2], u64> {
|
||||||
|
let mut new_pairs = HashMap::new();
|
||||||
|
for entry in polymer_pairs {
|
||||||
|
let pair = entry.0;
|
||||||
|
if rules.contains_key(pair) {
|
||||||
|
let rule = *rules.get(pair).unwrap();
|
||||||
|
|
||||||
|
let left_pair = [pair[0], rule];
|
||||||
|
let left_entry = new_pairs.entry(left_pair).or_insert(0);
|
||||||
|
*left_entry += entry.1;
|
||||||
|
|
||||||
|
let right_pair = [rule, pair[1]];
|
||||||
|
let right_entry = new_pairs.entry(right_pair).or_insert(0);
|
||||||
|
*right_entry += entry.1;
|
||||||
|
} else {
|
||||||
|
let new_entry = new_pairs.entry(*entry.0).or_insert(0);
|
||||||
|
*new_entry = *entry.1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new_pairs;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(input: &InputData) -> u64 {
|
||||||
|
let polymer_template = &input.polymer_template;
|
||||||
|
let mut polymer_pairs = HashMap::new();
|
||||||
|
for i in 0..polymer_template.len()-1 {
|
||||||
|
let pair = [
|
||||||
|
polymer_template.chars().nth(i).unwrap(),
|
||||||
|
polymer_template.chars().nth(i+1).unwrap()
|
||||||
|
];
|
||||||
|
let entry = polymer_pairs.entry(pair).or_insert(0);
|
||||||
|
*entry += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for _ in 0..40 {
|
||||||
|
polymer_pairs = expand_polymer(&polymer_pairs, &input.rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut element_amounts = HashMap::new();
|
||||||
|
for entry in polymer_pairs {
|
||||||
|
for c in entry.0 {
|
||||||
|
let amount = element_amounts.entry(c).or_insert(0);
|
||||||
|
*amount += entry.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)/2 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -64,25 +111,50 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn part1_example() {
|
fn part1_example() {
|
||||||
let polymer_template = String::from("NNCB");
|
let polymer_template = String::from("NNCB");
|
||||||
let rules = vec![
|
let rules = HashMap::from([
|
||||||
InsertionRule(['C', 'H'], 'B'),
|
(['C', 'H'], 'B'),
|
||||||
InsertionRule(['H', 'H'], 'N'),
|
(['H', 'H'], 'N'),
|
||||||
InsertionRule(['C', 'B'], 'H'),
|
(['C', 'B'], 'H'),
|
||||||
InsertionRule(['N', 'H'], 'C'),
|
(['N', 'H'], 'C'),
|
||||||
InsertionRule(['H', 'B'], 'C'),
|
(['H', 'B'], 'C'),
|
||||||
InsertionRule(['H', 'C'], 'B'),
|
(['H', 'C'], 'B'),
|
||||||
InsertionRule(['H', 'N'], 'C'),
|
(['H', 'N'], 'C'),
|
||||||
InsertionRule(['N', 'N'], 'C'),
|
(['N', 'N'], 'C'),
|
||||||
InsertionRule(['B', 'H'], 'H'),
|
(['B', 'H'], 'H'),
|
||||||
InsertionRule(['N', 'C'], 'B'),
|
(['N', 'C'], 'B'),
|
||||||
InsertionRule(['N', 'B'], 'B'),
|
(['N', 'B'], 'B'),
|
||||||
InsertionRule(['B', 'N'], 'B'),
|
(['B', 'N'], 'B'),
|
||||||
InsertionRule(['B', 'B'], 'N'),
|
(['B', 'B'], 'N'),
|
||||||
InsertionRule(['B', 'C'], 'B'),
|
(['B', 'C'], 'B'),
|
||||||
InsertionRule(['C', 'C'], 'N'),
|
(['C', 'C'], 'N'),
|
||||||
InsertionRule(['C', 'N'], 'C')
|
(['C', 'N'], 'C')
|
||||||
];
|
]);
|
||||||
let result = part1(&InputData { polymer_template, rules });
|
let result = part1(&InputData { polymer_template, rules });
|
||||||
assert_eq!(result, 1588);
|
assert_eq!(result, 1588);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2_example() {
|
||||||
|
let polymer_template = String::from("NNCB");
|
||||||
|
let rules = HashMap::from([
|
||||||
|
(['C', 'H'], 'B'),
|
||||||
|
(['H', 'H'], 'N'),
|
||||||
|
(['C', 'B'], 'H'),
|
||||||
|
(['N', 'H'], 'C'),
|
||||||
|
(['H', 'B'], 'C'),
|
||||||
|
(['H', 'C'], 'B'),
|
||||||
|
(['H', 'N'], 'C'),
|
||||||
|
(['N', 'N'], 'C'),
|
||||||
|
(['B', 'H'], 'H'),
|
||||||
|
(['N', 'C'], 'B'),
|
||||||
|
(['N', 'B'], 'B'),
|
||||||
|
(['B', 'N'], 'B'),
|
||||||
|
(['B', 'B'], 'N'),
|
||||||
|
(['B', 'C'], 'B'),
|
||||||
|
(['C', 'C'], 'N'),
|
||||||
|
(['C', 'N'], 'C')
|
||||||
|
]);
|
||||||
|
let result = part2(&InputData { polymer_template, rules });
|
||||||
|
assert_eq!(result, 2188189693529);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ fn run(day: i32, part: i32, input_filename: &str) {
|
|||||||
"13.1" => println!("{}", day13::part1(&day13::parse_input(&contents))),
|
"13.1" => println!("{}", day13::part1(&day13::parse_input(&contents))),
|
||||||
"13.2" => day13::part2(&day13::parse_input(&contents)),
|
"13.2" => day13::part2(&day13::parse_input(&contents)),
|
||||||
"14.1" => println!("{}", day14::part1(&day14::parse_input(&contents))),
|
"14.1" => println!("{}", day14::part1(&day14::parse_input(&contents))),
|
||||||
|
"14.2" => println!("{}", day14::part2(&day14::parse_input(&contents))),
|
||||||
_ => println!("Day {} part {} not found", day, part)
|
_ => println!("Day {} part {} not found", day, part)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user