From c2389e93af8fdda5e4aa5949a7193be93e2ae486 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 16 Dec 2023 11:38:50 +0100 Subject: [PATCH] Implement 2023 day 16 part 1 --- 2023/samples/.gitkeep | 0 2023/src/common.rs | 15 ++++++ 2023/src/day16.rs | 112 +++++++++++++++++++++++++++++++++++++++- 2023/src/samples/16.txt | 10 ++++ 4 files changed, 135 insertions(+), 2 deletions(-) delete mode 100644 2023/samples/.gitkeep create mode 100644 2023/src/samples/16.txt diff --git a/2023/samples/.gitkeep b/2023/samples/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/2023/src/common.rs b/2023/src/common.rs index 3e848b8..1bf8edd 100644 --- a/2023/src/common.rs +++ b/2023/src/common.rs @@ -289,6 +289,21 @@ impl> Grid { } } +impl Grid> { + pub fn zeroed(width: usize, height: usize) -> Self { + let mut data = vec![0; (width + 1) * height]; + + for line_end in data[width..].iter_mut().step_by(width + 1) { + *line_end = b'\n'; + } + + Self { + width: width + 1, + data, + } + } +} + impl + AsRef<[u8]>> Grid { pub fn rows_mut(&mut self) -> impl Iterator { let width = self.width(); diff --git a/2023/src/day16.rs b/2023/src/day16.rs index 7c1760f..e8ab584 100644 --- a/2023/src/day16.rs +++ b/2023/src/day16.rs @@ -1,7 +1,115 @@ -pub fn part1(_input: &[u8]) -> anyhow::Result { - anyhow::bail!("Not implemented") +use crate::common::Grid; + +#[derive(Clone, Copy)] +enum Direction { + Up = 0, + Left = 1, + Down = 2, + Right = 3, +} + +impl Direction { + fn bit(self) -> u8 { + 1 << self as u8 + } +} + +pub fn part1(input: &[u8]) -> anyhow::Result { + let map = Grid::new(input)?; + let mut state = Grid::zeroed(map.width(), map.height()); + state[0][0] = Direction::Right.bit(); + + let mut todo = Vec::new(); + todo.push((Direction::Right, 0, 0)); + + let mut energized = 1; + + while let Some((dir, x, y)) = todo.pop() { + let mut enqueue = |dir: Direction, x: usize, y| { + let state = &mut state[y][x]; + if state == &0 { + energized += 1; + } + if *state & dir.bit() == 0 { + *state |= dir.bit(); + todo.push((dir, x, y)); + } + }; + + let new_dir = match (map[y][x], dir) { + (b'/', Direction::Left) => Direction::Down, + (b'/', Direction::Up) => Direction::Right, + (b'/', Direction::Down) => Direction::Left, + (b'/', Direction::Right) => Direction::Up, + (b'\\', Direction::Left) => Direction::Up, + (b'\\', Direction::Up) => Direction::Left, + (b'\\', Direction::Down) => Direction::Right, + (b'\\', Direction::Right) => Direction::Down, + (b'|', Direction::Right) | (b'|', Direction::Left) => { + if y > 0 { + enqueue(Direction::Up, x, y - 1); + } + if y + 1 < map.height() { + enqueue(Direction::Down, x, y + 1); + } + continue; + } + (b'-', Direction::Up) | (b'-', Direction::Down) => { + if x > 0 { + enqueue(Direction::Left, x - 1, y); + } + if x + 1 < map.width() { + enqueue(Direction::Right, x + 1, y); + } + continue; + } + (_, dir) => dir, + }; + + match new_dir { + Direction::Up => { + if y > 0 { + enqueue(new_dir, x, y - 1); + } + } + Direction::Left => { + if x > 0 { + enqueue(new_dir, x - 1, y); + } + } + Direction::Down => { + if y + 1 < map.height() { + enqueue(new_dir, x, y + 1); + } + } + Direction::Right => { + if x + 1 < map.width() { + enqueue(new_dir, x + 1, y); + } + } + } + } + + Ok(energized.to_string()) } pub fn part2(_input: &[u8]) -> anyhow::Result { anyhow::bail!("Not implemented") } + +#[cfg(test)] +mod tests { + use super::*; + + const SAMPLE: &[u8] = include_bytes!("samples/16.txt"); + + #[test] + fn sample_part1() { + assert_eq!("46", part1(SAMPLE).unwrap()); + } + + // #[test] + // fn sample_part2() { + // assert_eq!("64", part2(SAMPLE).unwrap()); + // } +} diff --git a/2023/src/samples/16.txt b/2023/src/samples/16.txt new file mode 100644 index 0000000..d6805ce --- /dev/null +++ b/2023/src/samples/16.txt @@ -0,0 +1,10 @@ +.|...\.... +|.-.\..... +.....|-... +........|. +.......... +.........\ +..../.\\.. +.-.-/..|.. +.|....-|.\ +..//.|....