summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Wernick <justin@worthe-it.co.za>2023-12-15 11:02:52 +0200
committerJustin Wernick <justin@worthe-it.co.za>2023-12-15 11:02:52 +0200
commit8b96dde3ef9b7b37ac8e94f260e1ddc35fa12e41 (patch)
tree2ff7c36efd45e4ba4fb91b00912fc62eb1df42b8
parentdc97d6fe01ca7afd2618540f9a4470b6a3849674 (diff)
Day 15 part 2
-rw-r--r--2023/src/bin/day_15.rs124
1 files changed, 115 insertions, 9 deletions
diff --git a/2023/src/bin/day_15.rs b/2023/src/bin/day_15.rs
index badb34f..429e7f4 100644
--- a/2023/src/bin/day_15.rs
+++ b/2023/src/bin/day_15.rs
@@ -1,30 +1,136 @@
use std::fs;
+use nom::{
+ branch::alt,
+ bytes::complete::tag,
+ character::complete::{alpha1, u32},
+ combinator::{consumed, map, value},
+ multi::separated_list1,
+ sequence::{pair, preceded},
+ IResult,
+};
+
fn main() -> Result<(), Box<dyn std::error::Error>> {
let input = fs::read_to_string("inputs/day_15.txt")?;
- let parsed = InitializationInstructions::parse(&input);
+ let parsed = InitializationInstructions::parser(&input).unwrap().1;
dbg!(&parsed.hash_sum());
+ dbg!(&parsed.final_focusing_power());
Ok(())
}
#[derive(Debug)]
-struct InitializationInstructions(Vec<String>);
+struct InitializationInstructions(Vec<Instruction>);
+
+#[derive(Debug)]
+struct Instruction {
+ instruction: String,
+ label: String,
+ action: Action,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum Action {
+ Remove,
+ Insert(u32),
+}
+
+#[derive(Default, Debug, Clone)]
+struct LensBox {
+ lenses: Vec<Lens>,
+}
+
+#[derive(Debug, Clone)]
+struct Lens {
+ label: String,
+ power: u32,
+}
impl InitializationInstructions {
- fn parse(input: &str) -> Self {
- Self(input.trim().split(",").map(|s| s.to_owned()).collect())
+ fn parser(input: &str) -> IResult<&str, Self> {
+ map(
+ separated_list1(tag(","), Instruction::parser),
+ InitializationInstructions,
+ )(input)
}
- fn hash_sum(&self) -> u32 {
- self.0.iter().map(|s| hash(&s)).sum()
+ fn hash_sum(&self) -> usize {
+ self.0.iter().map(|i| hash(&i.instruction)).sum()
+ }
+
+ fn final_focusing_power(&self) -> u32 {
+ let mut boxes = vec![LensBox::default(); 256];
+ for instruction in &self.0 {
+ let box_index = hash(&instruction.label);
+ let lens_box = &mut boxes[box_index];
+ match instruction.action {
+ Action::Remove => {
+ lens_box
+ .lenses
+ .retain(|lens| lens.label != instruction.label);
+ }
+ Action::Insert(power) => {
+ let existing_position = lens_box
+ .lenses
+ .iter()
+ .position(|lens| lens.label == instruction.label);
+ match existing_position {
+ Some(position) => {
+ lens_box.lenses[position].power = power;
+ }
+ None => {
+ lens_box.lenses.push(Lens {
+ label: instruction.label.clone(),
+ power,
+ });
+ }
+ }
+ }
+ }
+ }
+
+ boxes
+ .into_iter()
+ .enumerate()
+ .flat_map(|(box_index, lens_box)| {
+ lens_box
+ .lenses
+ .into_iter()
+ .enumerate()
+ .map(move |(lens_index, lens)| {
+ (box_index as u32 + 1) * (lens_index as u32 + 1) * lens.power
+ })
+ })
+ .sum()
+ }
+}
+
+impl Instruction {
+ fn parser(input: &str) -> IResult<&str, Self> {
+ map(
+ consumed(pair(alpha1, Action::parser)),
+ |(instruction, (label, action))| Instruction {
+ instruction: instruction.to_owned(),
+ label: label.to_owned(),
+ action,
+ },
+ )(input)
+ }
+}
+
+impl Action {
+ fn parser(input: &str) -> IResult<&str, Self> {
+ alt((
+ value(Action::Remove, tag("-")),
+ map(preceded(tag("="), u32), Action::Insert),
+ ))(input)
}
}
-fn hash(input: &str) -> u32 {
- let mut result: u32 = 0;
+fn hash(input: &str) -> usize {
+ let mut result: usize = 0;
for c in input.bytes() {
- result += Into::<u32>::into(c);
+ result += Into::<usize>::into(c);
result *= 17;
result %= 256;
}