From 842def62dc622a7708753f1bcb3db59a24fee935 Mon Sep 17 00:00:00 2001 From: Keenan Tims Date: Fri, 15 Dec 2023 23:54:22 -0800 Subject: [PATCH] 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. --- 16/src/main.rs | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/16/src/main.rs b/16/src/main.rs index 6611bc7..e7b6d0d 100644 --- a/16/src/main.rs +++ b/16/src/main.rs @@ -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();