diff --git a/src/bin/day22.rs b/src/bin/day22.rs index 0fa5ded..4b92809 100644 --- a/src/bin/day22.rs +++ b/src/bin/day22.rs @@ -5,6 +5,10 @@ use aoc_2022::*; type Input = MonkeyMap; type Output = isize; +type Position = Vector2D; +type Direction = Vector2D; +type Boundary = Vector2D; + enum Instruction { Move(usize), TurnLeft, @@ -19,56 +23,90 @@ enum Orientation { struct MonkeyMap { map: Vec>, - boundaries: HashMap, + boundaries: HashMap, instructions: Vec, } +fn wrapping_step(position: usize, diff: isize, range: Boundary) -> usize { + let (lower, upper) = (range.x(), range.y()); + 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); + fn next(&self, state: &State<'_>) -> (Position, Direction); } 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; + fn next(&self, state: &State<'_>) -> (Position, Direction) { + let h_bound = state.input.boundaries[&Orientation::Horizontal(state.position.y())]; + let v_bound = state.input.boundaries[&Orientation::Vertical(state.position.x())]; ( - Self::step(state.x, dx, h_bound.0, h_bound.1), - Self::step(state.y, dy, v_bound.0, v_bound.1), + Position::new( + wrapping_step(state.position.x(), state.direction.x(), h_bound), + wrapping_step(state.position.y(), state.direction.y(), v_bound), + ), + state.direction, + ) + } +} + +struct Face { + horizontal_bound: Boundary, + vertical_bound: Boundary, +} + +struct Wrap3D { + faces: Vec, +} +impl Wrap3D { + fn face(&self, position: Position) -> &Face { + let (x, y) = (position.x(), position.y()); + + for f in &self.faces {} + todo!() + } +} +impl Wrap for Wrap3D { + fn next(&self, state: &State<'_>) -> (Position, Direction) { + let face = self.face(state.position); + + ( + Position::new( + wrapping_step( + state.position.x(), + state.direction.x(), + face.horizontal_bound, + ), + wrapping_step(state.position.y(), state.direction.y(), face.vertical_bound), + ), + state.direction, ) } } struct State<'a> { input: &'a Input, - y: usize, - x: usize, - direction: (isize, isize), + position: Position, + direction: Direction, } impl<'a> State<'a> { fn new(input: &'a Input) -> State<'a> { Self { input, - y: 0, - x: input.boundaries[&Orientation::Horizontal(0)].0, - direction: (1, 0), + position: Position::new(input.boundaries[&Orientation::Horizontal(0)].x(), 0), + direction: Direction::new(1, 0), } } fn is_blocked(&self, wrapper: &impl Wrap) -> bool { - let (x, y) = wrapper.next(self); - self.input.map[y][x] == '#' + let (next_position, _) = wrapper.next(self); + self.input.map[next_position] == '#' } fn step(&mut self, wrapper: &impl Wrap, steps: usize) { @@ -76,18 +114,18 @@ impl<'a> State<'a> { if self.is_blocked(wrapper) { return; } - (self.x, self.y) = wrapper.next(self); + (self.position, self.direction) = wrapper.next(self); } } fn turn_left(&mut self) { - let (x, y) = self.direction; - self.direction = (y, -x); + let previous = self.direction; + self.direction = Direction::new(previous.y(), -previous.x()); } fn turn_right(&mut self) { - let (x, y) = self.direction; - self.direction = (-y, x); + let previous = self.direction; + self.direction = Direction::new(-previous.y(), previous.x()); } } @@ -110,7 +148,9 @@ fn solve(wrapper: &impl Wrap, input: &Input) -> Output { state }); - (1000 * (final_state.y + 1) + 4 * (final_state.x + 1) + DIRECTIONS[&final_state.direction]) + (1000 * (final_state.position.y() + 1) + + 4 * (final_state.position.x() + 1) + + DIRECTIONS[&(final_state.direction.x(), final_state.direction.y())]) .try_into() .unwrap() } @@ -133,7 +173,7 @@ impl Solution for Day22 { let mut last_non_empty = first_non_empty.skip_while(|&(_, &c)| c != ' '); let end = last_non_empty.next().unwrap_or((map[row].len(), &'_')).0; - boundaries.insert(Orientation::Horizontal(row), (start, end)); + boundaries.insert(Orientation::Horizontal(row), Boundary::new(start, end)); } for col in 0..map[0].len() { @@ -145,7 +185,7 @@ impl Solution for Day22 { let mut last_non_empty = first_non_empty.skip_while(|&(_, &c)| c != ' '); let end = last_non_empty.next().unwrap_or((map.len(), &'_')).0; - boundaries.insert(Orientation::Vertical(col), (start, end)); + boundaries.insert(Orientation::Vertical(col), Boundary::new(start, end)); } let unparsed_instructions_str = instructions.trim_end(); @@ -185,8 +225,9 @@ impl Solution for Day22 { solve(&Wrap2D, input) } - fn part_2(_input: &Input) -> Output { - todo!() + fn part_2(input: &Input) -> Output { + let wrapper = Wrap2D; + solve(&wrapper, input) } }