Skip to content

Commit

Permalink
more day 16 optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
kcaffrey committed Dec 16, 2023
1 parent 9187910 commit d2cc016
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 46 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) | `134.7µs` | `5.8ms` |
| [Day 16](./src/bin/16.rs) | `124.0µs` | `5.3ms` |

**Total: 12.95ms**
**Total: 12.44ms**
<!--- benchmarking table --->

---
Expand Down
68 changes: 24 additions & 44 deletions src/bin/16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,33 @@ pub fn part_two(input: &str) -> Option<u32> {

fn energize_count(grid: &Grid, start: Coordinate, start_dir: Direction) -> u32 {
let mut energized = vec![false; grid.height * grid.width];
let mut queue = VecDeque::new();
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() {
let mut queue = VecDeque::with_capacity(1_000);
queue.push_back((start, start_dir));
while let Some((cur, dir)) = queue.pop_front() {
use Direction::{East, North, South, West};
use Tile::{Empty, HorizontalSplitter, LeftMirror, RightMirror, VerticalSplitter};

let i = cur.row * grid.width + cur.col;
let tile = grid.tiles[i];
let was_energized = energized[i];
if was_energized && (tile == HorizontalSplitter || tile == VerticalSplitter) {
continue;
}
energized[i] = true;

let mut do_next = |next_dir| {
let Some(next) = grid.move_in_dir(cur, next_dir) else {
return;
let next = match (cur, next_dir) {
(c, North) if c.row == 0 => return,
(c, South) if c.row + 1 == grid.height => return,
(c, West) if c.col == 0 => return,
(c, East) if c.col + 1 == grid.width => return,
(_, North) => coord!(cur.row - 1, cur.col),
(_, South) => coord!(cur.row + 1, cur.col),
(_, East) => coord!(cur.row, cur.col + 1),
(_, West) => coord!(cur.row, cur.col - 1),
};
let tile = grid.get_tile(next);
let i = next.row * grid.width + next.col;
let was_energized = energized[i];
energized[i] = true;
match (tile, was_energized) {
// If we hit a splitter that was already energized, we know we are entering a loop so we can stop
(Tile::HorizontalSplitter, true) | (Tile::VerticalSplitter, true) => {}

// Otherwise keep going
_ => queue.push_back((next, next_dir, tile)),
}
queue.push_back((next, next_dir));
};
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),
Expand Down Expand Up @@ -104,37 +109,12 @@ impl Grid {
pub fn get_tile(&self, coord: Coordinate) -> Tile {
self.tiles[coord.row * self.width + coord.col]
}

fn move_in_dir(&self, coord: Coordinate, dir: Direction) -> Option<Coordinate> {
coord
.move_in_dir(dir)
.filter(|&c| c.row < self.height && c.col < self.width)
}
}

impl Coordinate {
const fn new(row: usize, col: usize) -> Self {
Self { row, col }
}

const fn move_in_dir(self, dir: Direction) -> Option<Self> {
Some(match dir {
Direction::North => {
if self.row == 0 {
return None;
}
Self::new(self.row - 1, self.col)
}
Direction::South => Self::new(self.row + 1, self.col),
Direction::East => Self::new(self.row, self.col + 1),
Direction::West => {
if self.col == 0 {
return None;
}
Self::new(self.row, self.col - 1)
}
})
}
}

#[derive(Error, Debug)]
Expand Down

0 comments on commit d2cc016

Please sign in to comment.