day16: use tail recursion unstead of passing mutable state
This commit is contained in:
		| @@ -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( | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user