From 8b96dde3ef9b7b37ac8e94f260e1ddc35fa12e41 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Fri, 15 Dec 2023 11:02:52 +0200 Subject: Day 15 part 2 --- 2023/src/bin/day_15.rs | 124 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file 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> { 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); +struct InitializationInstructions(Vec); + +#[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, +} + +#[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::::into(c); + result += Into::::into(c); result *= 17; result %= 256; } -- cgit v1.2.3