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:
parent
427a0c766b
commit
842def62dc
@ -1,4 +1,3 @@
|
|||||||
use std::collections::HashSet;
|
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufRead, BufReader, Lines};
|
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 {
|
fn cast_ray<'a>(&'a mut self, pos: (i64, i64), dir: FromDirection) -> VisitState {
|
||||||
let mut state = self.empty_state();
|
let mut state = self.empty_state();
|
||||||
let mut new_rays = self.cast_ray_inner(&mut state, pos, dir);
|
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();
|
|
||||||
}
|
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
fn cast_ray_inner<'a>(
|
fn cast_ray_inner<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
state: &'a mut VisitState,
|
state: &'a mut VisitState,
|
||||||
mut pos: (i64, i64),
|
pos: (i64, i64),
|
||||||
mut dir: FromDirection,
|
dir: FromDirection,
|
||||||
) -> Vec<((i64, i64), FromDirection)> {
|
) {
|
||||||
let mut new_rays = Vec::new();
|
if pos.0 >= 0
|
||||||
|
&& pos.1 >= 0
|
||||||
while pos.0 >= 0 && pos.1 >= 0 && pos.0 < self.width() && pos.1 < self.height() {
|
&& pos.0 < self.width()
|
||||||
if !state.visit(pos, dir) {
|
&& pos.1 < self.height()
|
||||||
break;
|
&& state.visit(pos, dir)
|
||||||
}
|
{
|
||||||
dir = 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) => dir,
|
Interaction::One(dir) => self.cast_ray_inner(state, dir.goes_pos(pos), dir),
|
||||||
Interaction::Two((dir1, dir2)) => {
|
Interaction::Two((dir1, dir2)) => {
|
||||||
new_rays.push((pos, dir1));
|
self.cast_ray_inner(state, dir1.goes_pos(pos), dir1);
|
||||||
dir2
|
self.cast_ray_inner(state, dir2.goes_pos(pos), dir2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
pos = dir.goes_pos(pos);
|
|
||||||
}
|
}
|
||||||
new_rays
|
|
||||||
}
|
}
|
||||||
fn empty_state(&self) -> VisitState {
|
fn empty_state(&self) -> VisitState {
|
||||||
let mut visited_from = Vec::new();
|
let mut visited_from = Vec::new();
|
||||||
|
Loading…
Reference in New Issue
Block a user