diff --git a/src/bin/day22.rs b/src/bin/day22.rs index 74b043e..c37ea9c 100644 --- a/src/bin/day22.rs +++ b/src/bin/day22.rs @@ -23,10 +23,30 @@ struct MonkeyMap { instructions: Vec, } -fn step_with_wrap(position: usize, diff: isize, lower: usize, upper: usize) -> usize { - let range_size = (upper - lower) as isize; - (lower as isize + (position as isize + diff - lower as isize + range_size) % range_size) - as usize +trait Wrap { + fn next(&self, state: &State<'_>) -> (usize, usize); +} + +struct Wrap2D; +impl Wrap2D { + fn step(position: usize, diff: isize, lower: usize, upper: usize) -> usize { + let range_size = (upper - lower) as isize; + (lower as isize + (position as isize + diff - lower as isize + range_size) % range_size) + as usize + } +} +impl Wrap for Wrap2D { + fn next(&self, state: &State<'_>) -> (usize, usize) { + let h_bound = state.input.boundaries[&Orientation::Horizontal(state.y)]; + let v_bound = state.input.boundaries[&Orientation::Vertical(state.x)]; + + let (dx, dy) = state.direction; + + ( + Self::step(state.x, dx, h_bound.0, h_bound.1), + Self::step(state.y, dy, v_bound.0, v_bound.1), + ) + } } struct State<'a> { @@ -46,29 +66,17 @@ impl<'a> State<'a> { } } - fn next(&self) -> (usize, usize) { - let h_bound = self.input.boundaries[&Orientation::Horizontal(self.y)]; - let v_bound = self.input.boundaries[&Orientation::Vertical(self.x)]; - - let (dx, dy) = self.direction; - - ( - step_with_wrap(self.x, dx, h_bound.0, h_bound.1), - step_with_wrap(self.y, dy, v_bound.0, v_bound.1), - ) - } - - fn is_blocked(&self) -> bool { - let (x, y) = self.next(); + fn is_blocked(&self, wrapper: &impl Wrap) -> bool { + let (x, y) = wrapper.next(self); self.input.map[y][x] == '#' } - fn step(&mut self, steps: usize) { + fn step(&mut self, wrapper: &impl Wrap, steps: usize) { for _ in 0..steps { - if self.is_blocked() { + if self.is_blocked(wrapper) { return; } - (self.x, self.y) = self.next(); + (self.x, self.y) = wrapper.next(self); } } @@ -155,12 +163,14 @@ impl Solution for Day22 { } fn part_1(input: &Input) -> Output { + let wrapper = Wrap2D; + let final_state = input .instructions .iter() .fold(State::new(input), |mut state, y| { match &y { - Instruction::Move(steps) => state.step(*steps), + Instruction::Move(steps) => state.step(&wrapper, *steps), Instruction::TurnLeft => state.turn_left(), Instruction::TurnRight => state.turn_right(), }