day16: use tail recursion unstead of passing mutable state
This commit is contained in:
parent
842def62dc
commit
da25b73eca
@ -41,12 +41,12 @@ enum FromDirection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FromDirection {
|
impl FromDirection {
|
||||||
fn mask(&self) -> u8 {
|
const fn mask(&self) -> u8 {
|
||||||
1 << *self as u8
|
1 << *self as u8
|
||||||
}
|
}
|
||||||
// return the new pos for a ray that will be from the direction.
|
// return the new pos for a ray that will be from the direction.
|
||||||
// a ray 'from' left 'goes' right
|
// a ray 'from' left 'goes' right
|
||||||
fn goes_pos(&self, pos: (i64, i64)) -> (i64, i64) {
|
const fn goes_pos(&self, pos: (i64, i64)) -> (i64, i64) {
|
||||||
match self {
|
match self {
|
||||||
Self::Left => (pos.0 + 1, pos.1),
|
Self::Left => (pos.0 + 1, pos.1),
|
||||||
Self::Right => (pos.0 - 1, pos.1),
|
Self::Right => (pos.0 - 1, pos.1),
|
||||||
@ -54,7 +54,7 @@ impl FromDirection {
|
|||||||
Self::Below => (pos.0, pos.1 - 1),
|
Self::Below => (pos.0, pos.1 - 1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn reflect_ne(&self) -> Self {
|
const fn reflect_ne(&self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Self::Left => Self::Below,
|
Self::Left => Self::Below,
|
||||||
Self::Right => Self::Above,
|
Self::Right => Self::Above,
|
||||||
@ -62,7 +62,7 @@ impl FromDirection {
|
|||||||
Self::Below => Self::Left,
|
Self::Below => Self::Left,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn opposite(&self) -> FromDirection {
|
const fn opposite(&self) -> FromDirection {
|
||||||
match self {
|
match self {
|
||||||
Self::Left => Self::Right,
|
Self::Left => Self::Right,
|
||||||
Self::Right => Self::Left,
|
Self::Right => Self::Left,
|
||||||
@ -70,7 +70,7 @@ impl FromDirection {
|
|||||||
Self::Below => Self::Above,
|
Self::Below => Self::Above,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn reflect_se(&self) -> FromDirection {
|
const fn reflect_se(&self) -> FromDirection {
|
||||||
self.reflect_ne().opposite()
|
self.reflect_ne().opposite()
|
||||||
}
|
}
|
||||||
fn interact(&self, tile: char) -> Interaction {
|
fn interact(&self, tile: char) -> Interaction {
|
||||||
@ -90,7 +90,7 @@ impl FromDirection {
|
|||||||
Interaction::Two((FromDirection::Left, FromDirection::Right))
|
Interaction::Two((FromDirection::Left, FromDirection::Right))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
c => unimplemented!("invalid tile {}", c),
|
c => panic!("invalid tile {}", c),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,17 +150,15 @@ impl Contraption {
|
|||||||
fn width(&self) -> i64 {
|
fn width(&self) -> i64 {
|
||||||
self.tiles[0].len() as i64
|
self.tiles[0].len() as i64
|
||||||
}
|
}
|
||||||
fn cast_ray<'a>(&'a mut self, pos: (i64, i64), dir: FromDirection) -> VisitState {
|
fn cast_ray(&self, pos: (i64, i64), dir: FromDirection) -> VisitState {
|
||||||
let mut state = self.empty_state();
|
self.cast_ray_inner(self.empty_state(), pos, dir)
|
||||||
self.cast_ray_inner(&mut state, pos, dir);
|
|
||||||
state
|
|
||||||
}
|
}
|
||||||
fn cast_ray_inner<'a>(
|
fn cast_ray_inner(
|
||||||
&'a mut self,
|
&self,
|
||||||
state: &'a mut VisitState,
|
mut state: VisitState,
|
||||||
pos: (i64, i64),
|
pos: (i64, i64),
|
||||||
dir: FromDirection,
|
dir: FromDirection,
|
||||||
) {
|
) -> VisitState {
|
||||||
if pos.0 >= 0
|
if pos.0 >= 0
|
||||||
&& pos.1 >= 0
|
&& pos.1 >= 0
|
||||||
&& pos.0 < self.width()
|
&& pos.0 < self.width()
|
||||||
@ -169,11 +167,14 @@ impl Contraption {
|
|||||||
{
|
{
|
||||||
match dir.interact(self.tiles[pos.1 as usize][pos.0 as usize]) {
|
match dir.interact(self.tiles[pos.1 as usize][pos.0 as usize]) {
|
||||||
Interaction::One(dir) => self.cast_ray_inner(state, dir.goes_pos(pos), dir),
|
Interaction::One(dir) => self.cast_ray_inner(state, dir.goes_pos(pos), dir),
|
||||||
Interaction::Two((dir1, dir2)) => {
|
Interaction::Two((dir1, dir2)) => self.cast_ray_inner(
|
||||||
self.cast_ray_inner(state, dir1.goes_pos(pos), dir1);
|
self.cast_ray_inner(state, dir2.goes_pos(pos), dir2),
|
||||||
self.cast_ray_inner(state, dir2.goes_pos(pos), dir2);
|
dir1.goes_pos(pos),
|
||||||
|
dir1,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
};
|
} else {
|
||||||
|
state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn empty_state(&self) -> VisitState {
|
fn empty_state(&self) -> VisitState {
|
||||||
@ -198,14 +199,14 @@ impl<T: BufRead> From<Lines<T>> for Contraption {
|
|||||||
// PROBLEM 1 solution
|
// PROBLEM 1 solution
|
||||||
|
|
||||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||||
let mut contraption = Contraption::from(input);
|
let contraption = Contraption::from(input);
|
||||||
|
|
||||||
contraption.cast_ray((0, 0), FromDirection::Left).score()
|
contraption.cast_ray((0, 0), FromDirection::Left).score()
|
||||||
}
|
}
|
||||||
|
|
||||||
// PROBLEM 2 solution
|
// PROBLEM 2 solution
|
||||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||||
let mut contraption = Contraption::from(input);
|
let contraption = Contraption::from(input);
|
||||||
|
|
||||||
let rows_max = (0..contraption.height()).fold(0, |max_tiles, y| {
|
let rows_max = (0..contraption.height()).fold(0, |max_tiles, y| {
|
||||||
std::cmp::max(
|
std::cmp::max(
|
||||||
|
Loading…
Reference in New Issue
Block a user