day(22): switch to proper vectors
Signed-off-by: Matej Focko <me@mfocko.xyz>
This commit is contained in:
parent
ba28cdf340
commit
f237ebc936
1 changed files with 75 additions and 34 deletions
109
src/bin/day22.rs
109
src/bin/day22.rs
|
@ -5,6 +5,10 @@ use aoc_2022::*;
|
|||
type Input = MonkeyMap;
|
||||
type Output = isize;
|
||||
|
||||
type Position = Vector2D<usize>;
|
||||
type Direction = Vector2D<isize>;
|
||||
type Boundary = Vector2D<usize>;
|
||||
|
||||
enum Instruction {
|
||||
Move(usize),
|
||||
TurnLeft,
|
||||
|
@ -19,56 +23,90 @@ enum Orientation {
|
|||
|
||||
struct MonkeyMap {
|
||||
map: Vec<Vec<char>>,
|
||||
boundaries: HashMap<Orientation, (usize, usize)>,
|
||||
boundaries: HashMap<Orientation, Boundary>,
|
||||
instructions: Vec<Instruction>,
|
||||
}
|
||||
|
||||
trait Wrap {
|
||||
fn next(&self, state: &State<'_>) -> (usize, usize);
|
||||
}
|
||||
|
||||
struct Wrap2D;
|
||||
impl Wrap2D {
|
||||
fn step(position: usize, diff: isize, lower: usize, upper: usize) -> usize {
|
||||
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
|
||||
}
|
||||
}
|
||||
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;
|
||||
trait Wrap {
|
||||
fn next(&self, state: &State<'_>) -> (Position, Direction);
|
||||
}
|
||||
|
||||
struct Wrap2D;
|
||||
impl Wrap for Wrap2D {
|
||||
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<Face>,
|
||||
}
|
||||
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<Input, Output> 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<Input, Output> 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<Input, Output> for Day22 {
|
|||
solve(&Wrap2D, input)
|
||||
}
|
||||
|
||||
fn part_2(_input: &Input) -> Output {
|
||||
todo!()
|
||||
fn part_2(input: &Input) -> Output {
|
||||
let wrapper = Wrap2D;
|
||||
solve(&wrapper, input)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue