day(22): factor out wrapping to a trait
Signed-off-by: Matej Focko <me@mfocko.xyz>
This commit is contained in:
parent
775ee061d5
commit
fcdff3c129
1 changed files with 32 additions and 22 deletions
|
@ -23,10 +23,30 @@ struct MonkeyMap {
|
||||||
instructions: Vec<Instruction>,
|
instructions: Vec<Instruction>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step_with_wrap(position: usize, diff: isize, lower: usize, upper: usize) -> 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;
|
let range_size = (upper - lower) as isize;
|
||||||
(lower as isize + (position as isize + diff - lower as isize + range_size) % range_size)
|
(lower as isize + (position as isize + diff - lower as isize + range_size) % range_size)
|
||||||
as usize
|
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> {
|
struct State<'a> {
|
||||||
|
@ -46,29 +66,17 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next(&self) -> (usize, usize) {
|
fn is_blocked(&self, wrapper: &impl Wrap) -> bool {
|
||||||
let h_bound = self.input.boundaries[&Orientation::Horizontal(self.y)];
|
let (x, y) = wrapper.next(self);
|
||||||
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();
|
|
||||||
self.input.map[y][x] == '#'
|
self.input.map[y][x] == '#'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step(&mut self, steps: usize) {
|
fn step(&mut self, wrapper: &impl Wrap, steps: usize) {
|
||||||
for _ in 0..steps {
|
for _ in 0..steps {
|
||||||
if self.is_blocked() {
|
if self.is_blocked(wrapper) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(self.x, self.y) = self.next();
|
(self.x, self.y) = wrapper.next(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,12 +163,14 @@ impl Solution<Input, Output> for Day22 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part_1(input: &Input) -> Output {
|
fn part_1(input: &Input) -> Output {
|
||||||
|
let wrapper = Wrap2D;
|
||||||
|
|
||||||
let final_state = input
|
let final_state = input
|
||||||
.instructions
|
.instructions
|
||||||
.iter()
|
.iter()
|
||||||
.fold(State::new(input), |mut state, y| {
|
.fold(State::new(input), |mut state, y| {
|
||||||
match &y {
|
match &y {
|
||||||
Instruction::Move(steps) => state.step(*steps),
|
Instruction::Move(steps) => state.step(&wrapper, *steps),
|
||||||
Instruction::TurnLeft => state.turn_left(),
|
Instruction::TurnLeft => state.turn_left(),
|
||||||
Instruction::TurnRight => state.turn_right(),
|
Instruction::TurnRight => state.turn_right(),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue