day16: back to elegant recursion now that we track beams

problem 1 solution was busting the stack, so used an iterative approach,
but now that we track lit beams we can bail out early enough not to bust
the stack. performance is the same but it's much nicer.
This commit is contained in:
Keenan Tims 2023-12-15 23:54:22 -08:00
parent 427a0c766b
commit 842def62dc
Signed by: ktims
GPG Key ID: 11230674D69038D4

View File

@ -1,4 +1,3 @@
use std::collections::HashSet;
use std::fmt::Display;
use std::fs::File;
use std::io::{BufRead, BufReader, Lines};
@ -153,37 +152,29 @@ impl Contraption {
}
fn cast_ray<'a>(&'a mut self, pos: (i64, i64), dir: FromDirection) -> VisitState {
let mut state = self.empty_state();
let mut new_rays = self.cast_ray_inner(&mut state, pos, dir);
while new_rays.len() != 0 {
new_rays = new_rays
.iter()
.flat_map(|(pos, dir)| self.cast_ray_inner(&mut state, *pos, *dir))
.collect();
}
self.cast_ray_inner(&mut state, pos, dir);
state
}
fn cast_ray_inner<'a>(
&'a mut self,
state: &'a mut VisitState,
mut pos: (i64, i64),
mut dir: FromDirection,
) -> Vec<((i64, i64), FromDirection)> {
let mut new_rays = Vec::new();
while pos.0 >= 0 && pos.1 >= 0 && pos.0 < self.width() && pos.1 < self.height() {
if !state.visit(pos, dir) {
break;
}
dir = match dir.interact(self.tiles[pos.1 as usize][pos.0 as usize]) {
Interaction::One(dir) => dir,
pos: (i64, i64),
dir: FromDirection,
) {
if pos.0 >= 0
&& pos.1 >= 0
&& pos.0 < self.width()
&& pos.1 < self.height()
&& state.visit(pos, dir)
{
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::Two((dir1, dir2)) => {
new_rays.push((pos, dir1));
dir2
self.cast_ray_inner(state, dir1.goes_pos(pos), dir1);
self.cast_ray_inner(state, dir2.goes_pos(pos), dir2);
}
};
pos = dir.goes_pos(pos);
}
new_rays
}
fn empty_state(&self) -> VisitState {
let mut visited_from = Vec::new();