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 Input = MonkeyMap;
|
||||||
type Output = isize;
|
type Output = isize;
|
||||||
|
|
||||||
|
type Position = Vector2D<usize>;
|
||||||
|
type Direction = Vector2D<isize>;
|
||||||
|
type Boundary = Vector2D<usize>;
|
||||||
|
|
||||||
enum Instruction {
|
enum Instruction {
|
||||||
Move(usize),
|
Move(usize),
|
||||||
TurnLeft,
|
TurnLeft,
|
||||||
|
@ -19,56 +23,90 @@ enum Orientation {
|
||||||
|
|
||||||
struct MonkeyMap {
|
struct MonkeyMap {
|
||||||
map: Vec<Vec<char>>,
|
map: Vec<Vec<char>>,
|
||||||
boundaries: HashMap<Orientation, (usize, usize)>,
|
boundaries: HashMap<Orientation, Boundary>,
|
||||||
instructions: Vec<Instruction>,
|
instructions: Vec<Instruction>,
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Wrap {
|
fn wrapping_step(position: usize, diff: isize, range: Boundary) -> usize {
|
||||||
fn next(&self, state: &State<'_>) -> (usize, usize);
|
let (lower, upper) = (range.x(), range.y());
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
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),
|
Position::new(
|
||||||
Self::step(state.y, dy, v_bound.0, v_bound.1),
|
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> {
|
struct State<'a> {
|
||||||
input: &'a Input,
|
input: &'a Input,
|
||||||
y: usize,
|
position: Position,
|
||||||
x: usize,
|
direction: Direction,
|
||||||
direction: (isize, isize),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> State<'a> {
|
impl<'a> State<'a> {
|
||||||
fn new(input: &'a Input) -> State<'a> {
|
fn new(input: &'a Input) -> State<'a> {
|
||||||
Self {
|
Self {
|
||||||
input,
|
input,
|
||||||
y: 0,
|
position: Position::new(input.boundaries[&Orientation::Horizontal(0)].x(), 0),
|
||||||
x: input.boundaries[&Orientation::Horizontal(0)].0,
|
direction: Direction::new(1, 0),
|
||||||
direction: (1, 0),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_blocked(&self, wrapper: &impl Wrap) -> bool {
|
fn is_blocked(&self, wrapper: &impl Wrap) -> bool {
|
||||||
let (x, y) = wrapper.next(self);
|
let (next_position, _) = wrapper.next(self);
|
||||||
self.input.map[y][x] == '#'
|
self.input.map[next_position] == '#'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step(&mut self, wrapper: &impl Wrap, steps: usize) {
|
fn step(&mut self, wrapper: &impl Wrap, steps: usize) {
|
||||||
|
@ -76,18 +114,18 @@ impl<'a> State<'a> {
|
||||||
if self.is_blocked(wrapper) {
|
if self.is_blocked(wrapper) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(self.x, self.y) = wrapper.next(self);
|
(self.position, self.direction) = wrapper.next(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn turn_left(&mut self) {
|
fn turn_left(&mut self) {
|
||||||
let (x, y) = self.direction;
|
let previous = self.direction;
|
||||||
self.direction = (y, -x);
|
self.direction = Direction::new(previous.y(), -previous.x());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn turn_right(&mut self) {
|
fn turn_right(&mut self) {
|
||||||
let (x, y) = self.direction;
|
let previous = self.direction;
|
||||||
self.direction = (-y, x);
|
self.direction = Direction::new(-previous.y(), previous.x());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +148,9 @@ fn solve(wrapper: &impl Wrap, input: &Input) -> Output {
|
||||||
state
|
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()
|
.try_into()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
@ -133,7 +173,7 @@ impl Solution<Input, Output> for Day22 {
|
||||||
let mut last_non_empty = first_non_empty.skip_while(|&(_, &c)| c != ' ');
|
let mut last_non_empty = first_non_empty.skip_while(|&(_, &c)| c != ' ');
|
||||||
let end = last_non_empty.next().unwrap_or((map[row].len(), &'_')).0;
|
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() {
|
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 mut last_non_empty = first_non_empty.skip_while(|&(_, &c)| c != ' ');
|
||||||
let end = last_non_empty.next().unwrap_or((map.len(), &'_')).0;
|
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();
|
let unparsed_instructions_str = instructions.trim_end();
|
||||||
|
@ -185,8 +225,9 @@ impl Solution<Input, Output> for Day22 {
|
||||||
solve(&Wrap2D, input)
|
solve(&Wrap2D, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part_2(_input: &Input) -> Output {
|
fn part_2(input: &Input) -> Output {
|
||||||
todo!()
|
let wrapper = Wrap2D;
|
||||||
|
solve(&wrapper, input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue