From fffaaf063788ebc42156760a696440aa1057145d Mon Sep 17 00:00:00 2001 From: Matej Focko Date: Sat, 16 Dec 2023 22:16:12 +0100 Subject: [PATCH] day(16): add solution Signed-off-by: Matej Focko --- samples/day16.txt | 10 ++++ src/bin/day16.rs | 122 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 samples/day16.txt create mode 100644 src/bin/day16.rs diff --git a/samples/day16.txt b/samples/day16.txt new file mode 100644 index 0000000..d6805ce --- /dev/null +++ b/samples/day16.txt @@ -0,0 +1,10 @@ +.|...\.... +|.-.\..... +.....|-... +........|. +.......... +.........\ +..../.\\.. +.-.-/..|.. +.|....-|.\ +..//.|.... diff --git a/src/bin/day16.rs b/src/bin/day16.rs new file mode 100644 index 0000000..b32cc8c --- /dev/null +++ b/src/bin/day16.rs @@ -0,0 +1,122 @@ +use std::collections::VecDeque; + +use rayon::prelude::*; + +use aoc_2023::*; + +type Output1 = usize; +type Output2 = Output1; + +type Position = Vector2D; + +fn direction(d: &Position) -> i32 { + match (d.x(), d.y()) { + (1, _) => 1, + (_, 1) => 2, + (-1, _) => 4, + (_, -1) => 8, + _ => unreachable!("invalid direction"), + } +} + +fn next(c: char, d: Position) -> Vec { + match c { + '|' if d.x() != 0 => vec![Vector2D::new(0, 1), Vector2D::new(0, -1)], + '-' if d.y() != 0 => vec![Vector2D::new(1, 0), Vector2D::new(-1, 0)], + '/' => vec![Vector2D::new(-d.y(), -d.x())], + '\\' => vec![Vector2D::new(d.y(), d.x())], + _ => vec![d], + } +} + +// fn draw_energized(map: &[Vec]) { +// let mut formatted = String::new(); + +// for row in map { +// for &c in row { +// formatted += if c != 0 { "#" } else { "." }; +// } +// formatted += "\n"; +// } + +// debug!("Energized:\n{}", formatted); +// } + +struct Day16 { + map: Vec>, +} + +impl Day16 { + fn solve(&self, start_pos: Position, start_dir: Position) -> usize { + let mut visited = vec![vec![0; self.map[0].len()]; self.map.len()]; + + let mut q: VecDeque<(Position, Position)> = VecDeque::new(); + q.push_back((start_pos, start_dir)); + visited[start_pos] |= direction(&start_dir); + + while let Some((p, d)) = q.pop_front() { + for dp in next(self.map[p], d) { + if !in_range(&self.map, &(p + dp)) || visited[p + dp] & direction(&dp) != 0 { + continue; + } + + visited[p + dp] |= direction(&dp); + q.push_back((p + dp, dp)); + } + } + + // draw_energized(&visited); + + visited + .iter() + .map(|row| row.iter().filter(|&&c| c != 0).count()) + .sum() + } +} + +impl Solution for Day16 { + fn new>(pathname: P) -> Self { + Self { + map: file_to_string(pathname) + .lines() + .map(|l| l.chars().collect()) + .collect(), + } + } + + fn part_1(&mut self) -> Output1 { + self.solve(Vector2D::new(0, 0), Vector2D::new(1, 0)) + } + + fn part_2(&mut self) -> Output2 { + (0..self.map.len()) + .into_par_iter() + .flat_map(|y| { + vec![ + (Vector2D::new(0, y as isize), Vector2D::new(1, 0)), + ( + Vector2D::new(self.map[y].len() as isize - 1, y as isize), + Vector2D::new(-1, 0), + ), + ] + }) + .chain((0..self.map[0].len()).into_par_iter().flat_map(|x| { + vec![ + (Vector2D::new(x as isize, 0), Vector2D::new(0, 1)), + ( + Vector2D::new(x as isize, self.map.len() as isize - 1), + Vector2D::new(0, -1), + ), + ] + })) + .map(|(start_pos, start_dir)| self.solve(start_pos, start_dir)) + .max() + .unwrap() + } +} + +fn main() -> Result<()> { + Day16::main() +} + +test_sample!(day_16, Day16, 46, 51);