From 91879107c7f9021f345a57213b8da0e98514ca44 Mon Sep 17 00:00:00 2001 From: Kevin Caffrey Date: Sat, 16 Dec 2023 14:49:03 -0500 Subject: [PATCH] further simplify and optimize day 16 --- README.md | 4 +- src/bin/16.rs | 102 ++++++++++++-------------------------------------- 2 files changed, 25 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index 7547e5b..dc9dc2f 100644 --- a/README.md +++ b/README.md @@ -47,9 +47,9 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www. | [Day 13](./src/bin/13.rs) | `12.3µs` | `15.9µs` | | [Day 14](./src/bin/14.rs) | `25.0µs` | `4.5ms` | | [Day 15](./src/bin/15.rs) | `20.4µs` | `85.9µs` | -| [Day 16](./src/bin/16.rs) | `178.8µs` | `8.1ms` | +| [Day 16](./src/bin/16.rs) | `134.7µs` | `5.8ms` | -**Total: 15.29ms** +**Total: 12.95ms** --- diff --git a/src/bin/16.rs b/src/bin/16.rs index 8f30373..a72a3ef 100644 --- a/src/bin/16.rs +++ b/src/bin/16.rs @@ -32,10 +32,10 @@ fn energize_count(grid: &Grid, start: Coordinate, start_dir: Direction) -> u32 { energized[start.row * grid.width + start.col] = true; queue.push_back((start, start_dir, grid.get_tile(start))); while let Some((cur, dir, tile)) = queue.pop_front() { - for (next, next_dir) in tile - .next(dir) - .filter_map(|dir| grid.move_in_dir(cur, dir).map(|c| (c, dir))) - { + let mut do_next = |next_dir| { + let Some(next) = grid.move_in_dir(cur, next_dir) else { + return; + }; let tile = grid.get_tile(next); let i = next.row * grid.width + next.col; let was_energized = energized[i]; @@ -47,6 +47,25 @@ fn energize_count(grid: &Grid, start: Coordinate, start_dir: Direction) -> u32 { // Otherwise keep going _ => queue.push_back((next, next_dir, tile)), } + }; + use Direction::{East, North, South, West}; + use Tile::{Empty, HorizontalSplitter, LeftMirror, RightMirror, VerticalSplitter}; + match (tile, dir) { + (Empty, _) => do_next(dir), + (HorizontalSplitter, East) | (HorizontalSplitter, West) => do_next(dir), + (VerticalSplitter, North) | (VerticalSplitter, South) => do_next(dir), + (LeftMirror, East) | (RightMirror, West) => do_next(South), + (LeftMirror, West) | (RightMirror, East) => do_next(North), + (LeftMirror, North) | (RightMirror, South) => do_next(West), + (LeftMirror, South) | (RightMirror, North) => do_next(East), + (HorizontalSplitter, _) => { + do_next(West); + do_next(East); + } + (VerticalSplitter, _) => { + do_next(North); + do_next(South); + } } } energized.into_iter().filter(|&e| e).count() as u32 @@ -93,61 +112,6 @@ impl Grid { } } -impl Tile { - pub fn next(self, dir: Direction) -> impl Iterator { - let mut next = [None, None, None]; - if self.can_go_straight(dir) { - next[0] = Some(dir); - } - if self.can_turn_left(dir) { - next[1] = Some(dir.rotate_left()); - } - if self.can_turn_right(dir) { - next[2] = Some(dir.rotate_right()); - } - next.into_iter().flatten() - } - - const fn can_go_straight(self, dir: Direction) -> bool { - matches!( - (self, dir), - (Self::Empty, _) - | (Self::VerticalSplitter, Direction::South) - | (Self::VerticalSplitter, Direction::North) - | (Self::HorizontalSplitter, Direction::East) - | (Self::HorizontalSplitter, Direction::West) - ) - } - - const fn can_turn_left(self, dir: Direction) -> bool { - matches!( - (self, dir), - (Self::VerticalSplitter, Direction::East) - | (Self::VerticalSplitter, Direction::West) - | (Self::HorizontalSplitter, Direction::North) - | (Self::HorizontalSplitter, Direction::South) - | (Self::LeftMirror, Direction::North) - | (Self::LeftMirror, Direction::South) - | (Self::RightMirror, Direction::East) - | (Self::RightMirror, Direction::West) - ) - } - - const fn can_turn_right(self, dir: Direction) -> bool { - matches!( - (self, dir), - (Self::VerticalSplitter, Direction::East) - | (Self::VerticalSplitter, Direction::West) - | (Self::HorizontalSplitter, Direction::North) - | (Self::HorizontalSplitter, Direction::South) - | (Self::LeftMirror, Direction::East) - | (Self::LeftMirror, Direction::West) - | (Self::RightMirror, Direction::North) - | (Self::RightMirror, Direction::South) - ) - } -} - impl Coordinate { const fn new(row: usize, col: usize) -> Self { Self { row, col } @@ -173,26 +137,6 @@ impl Coordinate { } } -impl Direction { - const fn rotate_left(self) -> Self { - match self { - Direction::North => Direction::West, - Direction::South => Direction::East, - Direction::East => Direction::North, - Direction::West => Direction::South, - } - } - - const fn rotate_right(self) -> Self { - match self { - Direction::North => Direction::East, - Direction::South => Direction::West, - Direction::East => Direction::South, - Direction::West => Direction::North, - } - } -} - #[derive(Error, Debug)] enum ParseGridError { #[error("invalid tile character: {0}")]