This commit is contained in:
Shadowfacts 2023-12-16 14:31:18 -05:00
parent d9435c84ff
commit bebd52fcd1
3 changed files with 500 additions and 1 deletions

110
input/day16.txt Normal file
View File

@ -0,0 +1,110 @@
\.......................|..-.............../../.......|...............\.\.....|..../.............|............
........................../....../..............................-............-.-..--.........-...........\/...
....\............../...........-...-......|.............................\...............-........-....|.......
......\....|................./.\................/..................../.......................|..\......-......
.................../..................-./.................../.....-...................|......\.......|\...\./.
.....|........../....................\../..\.../.\.......-.............\...........\......|.\..-..........-...
..../............/.....\...................../..--\........|......\....-...|.-...../......-........../........
..............\.-............./........./....|\.......\..........|.................|.|.................-......
.....|..........-................-.../..........-........................\.......|.........................-..
.|.-......./....................\........-.............../..\.|.-\...........\./.................-............
................|/............................../..-.\..................-..../../...../.../..../..........|...
........................./.....................\..\....-....../-.....................\|.........././.-........
...\.....................-...../|............--......-..|...../.....|......|.../.\....|.............\|.......\
.........-...-.....|.........../...-/........|......./|............-.......-.....\.............\|....../......
.....|...|.................|...../.............|.................../..........\|..\......|..|....-............
...........................-.........\......\.............\...................-.....-.\.......-.....|.........
.................-.............-......./.............-..\./......|....-..-..........-....-............\.......
.\..\.......-......|........................\.............-.......................|.........|\.|..\......--/..
..........-.....||--........|........-....../...........|../...-.........../.....-.\..........|.......-.......
..........\..........|..................\.................-..../............/..........|.......-........../...
..--......../..........-..|........./.........-...../........-.................|..\............../.....-......
.....\.............|...../......../............./||..........................\............|...................
..-.................-|..-....................\.................|...\.....\............./......-.......\.......
............-../......\...../.-....-.....-....-./../......\..|..|............................|.../..|.........
-................./................................................|...............|....|.....-.....|....../..
...........-...................|...........\.......-..\.......-...........|..-....../........|...............|
.........|...|-........../...-..........|.........\.....||......./....|...............\......-......\...../...
....|.........|............\.-.......................................-.......................|.-..|.\...\.-...
.|....|....-/....................\\..........................|........\|...|..............\..|......-.\../....
..|.\......|..../.....|.......-....................|.\..\............/......................|.....\../../.....
.......|\\.\/......................./.............|................../.........|.....\-.......................
......................................../.../................\-..............-................./......\.......
............../............/\......./........................./......|............\/..........................
......./................|......../.........-............\.../.|....../....|...../..../......../...............
...................|............-\........../...\.......\....\.....-.........-./....|.........................
.....-..-\.................|\...........................|..........\........-...|.............................
..............................-.............-.......\......................../.......\|.......|...-....-......
\...................\..../.................\................|......-...-............./.-......................
........................./.|./...|..\.-............|.-.....-..........\....-..../.....|.......|...............
.................../......../..................|.|...............|.......|\.....|......|...............\/..|..
.........|....-......../........-./..|.../..|./...................-........|..................................
..|../............-......-.........................-..|....-................-..\....../...........|...........
....................-...............|.../.....|..../......../...|.......\.....-.....\..............-..\.-.....
...........\.........../............................................\......-................-.......|.....-...
..-............./.......-\...........|-..-../............../................................../...............
.................\.......\............../.|.......-...\............................................\.-........
.\....|....\......|........./.....--......................................|................\..|-..............
......../...............-..........................|...........................-.............-\.-..|..........
.......|......|/...\........./......../.....\.........\.......................-...........\..\................
.-..-../.............|................./../.................\........-......|.\.....||...................\|...
/......../....\.....|-..........\..............-.....|............/\......\...//....................\...-/....
................-...........-.-\-..........\.-./......../-................./../.\........................./...
-.........-.....|.....-..|..|.........|...................-..........\/.-.....................................
......./...../......\............-.|...............|..../.........|....\.................../..............|...
...........|.......|....|...............\........................\/..\......................................\.
......\........-.........................\..........\.............\......................\/.....\..|..........
......\...........|.........../..-............./........................../...-......../...............\..|...
..|............\../........../............\...|.......................-...............\-../.|...|\.....\......
.|....\.|....-|.........\......./.................../.|........|....../.--.\.....\..............-\\.........-.
......................./.......\...........|.\............-.....\.............\.........--......../.\..-.|../.
......../.............../......\.\....|.............../...........................-........-......../.........
.......|\.............|.../|/........../....\.....-....|.............-......./........\..\........\..|......-.
.............../...........-.....\..\....-...../...|......\...........................\...|...........|/......
.............|....../.................../..|.....................|.......|....//..............\...............
......./....\............................-.........................-/......../|......-....|.............../...
...........................|...................\...............................-.................|...........\
.............................-......./..../...................\.../...........-.|......................||.....
\....\....\...-./......../.........\................./................\...................|...........-.......
................-.../............/\..................\.\..-....../................./..........|...............
......../...\.......................\.......\..\......|.....|../..........\..........-.............|..........
../.........................................-\..........-.........|-./.....-...|..|.......\........-...../../.
.....|..........-......../|-..............|.................-...........|...\.....................\...........
.......|..............\....\.....-............../..\\..\.......-........./.........-..|...|................../
..........-.......-.-................../.........\\...../.....|..........\......./.|.............-...........\
..................................-..................|...........\../\...../..../...\................/........
...-.........................................................\.|..............\..................\............
-.|..|...................../../.|.......\.....|.....\.\...\.........-.................................../.....
...\./....../........\.......-.................\.........|............-.........../...........\.|.........|.\.
..........-...\.............-.-............-.-................/.....................|........|............-...
|......./............/..|..............\...............|.......|\................/....|.........|.........\..\
.....\../\./.....................-.............\..................|.|.........................................
............/......../.../.......\............/.........................\........................\............
....../..|.............../....................-.......\................................................|.....\
................................../.......././.......\.....|.\......-.........-..||......../........-.//......
........................\.......|............-....-...../..............................-............-....|...-
.....-.......|......\..|.........-....|......\......../..../.......\..........|....\.............||..\........
..........|...........-|.......\.......-....../...../..........||.......................\............-..|.....
.................../../..............................|....|................/........|-....|................/..
.....................\................/............................/-........./...|.............\...|..|\.....
.....\..\..........\......../......|.........-....-..-..|...........\....|./....\.\..\............../.........
.......-...............-....../...........-.......................|../...............|...|.........../..../...
.............|.../..................\..\..........-........||................\/...........-|..................
.............-..............-\.../.................|......\...../..........\...-.....-....../................\
.....-....................................-.........\/............../.............................|...........
./.|../......\\..........................................|..............\|/..-\..........................\....
...........-.........\............./....-........-....-....-.........\..\....-\...-...............--.........-
..\.............................\............................./\..........-.............-...-./........../....
.................../........\....|..-....|||./..............-......-./....................../..|...|..........
......\.........../............|\...|.-................../....................|\..|..\.............-./......|.
...........-...................-.|........................\...............|/..-...\...|/\...........|.........
............|..../..................................\.......................\........................-........
.\..........................|......|......../.|....................../.......\......\.............../.........
..........-.../............/..........................|....-......................|.-................|.-......
......../............-...|.....|......../-.....-|...|./.......-..................-\...........................
...............\.\/.-....././................-.../..../.............../-|.....-.......|......./..--...........
..........-\\.|-................./../..|.-.....--................../.................../.|.......-............
..\.................-..............-...............\.....|......................./..\.....--........./..../..\
.......-....../..............|..................\....|..|..........-.....|.|.-.........................\......
..../..\...\....................................||.|......................................|.......\/.........-
................\-.-.....||....\.........................-...................................................|

388
src/day16.rs Normal file
View File

@ -0,0 +1,388 @@
use std::{
collections::VecDeque,
fmt::{write, Debug},
};
pub fn run() {
let input = include_str!("../input/day16.txt");
// let input = r#"
// .|...\....
// |.-.\.....
// .....|-...
// ........|.
// ..........
// .........\
// ..../.\\..
// .-.-/..|..
// .|....-|.\
// ..//.|....
// "#;
let contraption: Contraption = input.into();
let visited = run_beam(
Beam {
row: 0,
col: -1,
direction: Direction::Right,
},
&contraption,
);
dbg!(visited.count());
dbg!(max_visited(&contraption));
}
#[derive(Clone)]
struct Contraption {
tiles: Vec<Vec<Tile>>,
width: usize,
height: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Tile {
Empty,
MirrorPos,
MirrorNeg,
SplitterVert,
SplitterHoriz,
}
impl Tile {
fn tile_char(&self) -> char {
match self {
Tile::Empty => '.',
Tile::MirrorPos => '/',
Tile::MirrorNeg => '\\',
Tile::SplitterVert => '|',
Tile::SplitterHoriz => '-',
}
}
}
impl Debug for Contraption {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Contraption(\n")?;
for row in self.tiles.iter() {
for tile in row {
write!(f, "{}", tile.tile_char())?;
}
}
write!(f, ")")
}
}
impl From<&str> for Contraption {
fn from(value: &str) -> Self {
let tiles = value
.trim()
.lines()
.map(|l| {
l.trim()
.chars()
.map(|c| match c {
'.' => Tile::Empty,
'/' => Tile::MirrorPos,
'\\' => Tile::MirrorNeg,
'|' => Tile::SplitterVert,
'-' => Tile::SplitterHoriz,
_ => panic!("unexpected char {:?}", c),
})
.collect::<Vec<_>>()
})
.collect::<Vec<_>>();
let width = tiles[0].len();
let height = tiles.len();
Self {
tiles,
width,
height,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Beam {
row: isize,
col: isize,
direction: Direction,
}
impl Beam {
fn move_current(&mut self) {
self.move_in(self.direction)
}
fn move_in(&mut self, dir: Direction) {
match dir {
Direction::Up => {
self.row -= 1;
}
Direction::Down => {
self.row += 1;
}
Direction::Left => {
self.col -= 1;
}
Direction::Right => {
self.col += 1;
}
}
}
fn in_bounds(&self, contraption: &Contraption) -> bool {
self.row >= 0
&& self.row < contraption.height as isize
&& self.col >= 0
&& self.col < contraption.width as isize
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Direction {
Up,
Down,
Left,
Right,
}
impl Direction {
fn is_vertical(&self) -> bool {
match self {
Direction::Up | Direction::Down => true,
_ => false,
}
}
fn is_horizontal(&self) -> bool {
match self {
Direction::Left | Direction::Right => true,
_ => false,
}
}
}
#[derive(Debug)]
struct Visited {
directions: Vec<Vec<u8>>,
}
impl Visited {
fn new(width: usize, height: usize) -> Self {
Self {
directions: vec![vec![0; width]; height],
}
}
fn visited_any(&self, row: usize, col: usize) -> bool {
self.directions[row][col] != 0
}
fn visited(&self, row: usize, col: usize, dir: Direction) -> bool {
(self.directions[row][col] >> (dir as usize)) & 1 == 1
}
fn visit(&mut self, row: usize, col: usize, dir: Direction) {
self.directions[row][col] |= 1 << dir as usize;
}
fn count(&self) -> usize {
self.directions
.iter()
.map(|row| row.iter().filter(|&&x| x != 0).count())
.sum()
}
}
fn run_beam(initial: Beam, contraption: &Contraption) -> Visited {
let mut visited = Visited::new(contraption.width, contraption.height);
let mut beams = VecDeque::from([initial]);
while let Some(mut beam) = beams.pop_front() {
beam.move_current();
while beam.in_bounds(contraption) {
if visited.visited(beam.row as usize, beam.col as usize, beam.direction) {
break;
}
visited.visit(beam.row as usize, beam.col as usize, beam.direction);
match contraption.tiles[beam.row as usize][beam.col as usize] {
Tile::Empty => (),
Tile::SplitterVert => {
if beam.direction.is_horizontal() {
beams.push_back(Beam {
row: beam.row,
col: beam.col,
direction: Direction::Up,
});
beam.direction = Direction::Down;
}
}
Tile::SplitterHoriz => {
if beam.direction.is_vertical() {
beams.push_back(Beam {
row: beam.row,
col: beam.col,
direction: Direction::Left,
});
beam.direction = Direction::Right;
}
}
Tile::MirrorPos => {
let new_dir = match beam.direction {
Direction::Up => Direction::Right,
Direction::Down => Direction::Left,
Direction::Left => Direction::Down,
Direction::Right => Direction::Up,
};
beam.direction = new_dir;
}
Tile::MirrorNeg => {
let new_dir = match beam.direction {
Direction::Up => Direction::Left,
Direction::Down => Direction::Right,
Direction::Left => Direction::Up,
Direction::Right => Direction::Down,
};
beam.direction = new_dir;
}
}
beam.move_current();
}
}
visited
}
fn debug_beams(contraption: &Contraption, visited: &Visited, beams: &VecDeque<Beam>) {
for row in 0..contraption.height {
for col in 0..contraption.width {
if let Some(beam) = beams
.iter()
.find(|b| b.row == row as isize && b.col == col as isize)
{
let c = match beam.direction {
Direction::Up => '^',
Direction::Down => 'V',
Direction::Left => '<',
Direction::Right => '>',
};
print!("{}", c);
} else if visited.visited_any(row, col) {
print!("#");
} else {
print!("{}", contraption.tiles[row][col].tile_char());
}
}
println!();
}
}
fn max_visited(contraption: &Contraption) -> usize {
let mut max = 0;
for col in 0..contraption.width {
max = max.max(
run_beam(
Beam {
row: -1,
col: col as isize,
direction: Direction::Down,
},
contraption,
)
.count(),
);
max = max.max(
run_beam(
Beam {
row: contraption.height as isize,
col: col as isize,
direction: Direction::Up,
},
contraption,
)
.count(),
);
}
for row in 0..contraption.height {
max = max.max(
run_beam(
Beam {
row: row as isize,
col: -1,
direction: Direction::Right,
},
contraption,
)
.count(),
);
max = max.max(
run_beam(
Beam {
row: row as isize,
col: contraption.width as isize,
direction: Direction::Left,
},
contraption,
)
.count(),
);
}
max
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_run_beam() {
let contraption: Contraption = r#"
.|...\....
|.-.\.....
.....|-...
........|.
..........
.........\
..../.\\..
.-.-/..|..
.|....-|.\
..//.|....
"#
.into();
let visited = run_beam(
Beam {
row: 0,
col: -1,
direction: Direction::Right,
},
&contraption,
);
assert_eq!(visited.count(), 46);
}
#[test]
fn test_max_visited() {
let contraption: Contraption = r#"
.|...\....
|.-.\.....
.....|-...
........|.
..........
.........\
..../.\\..
.-.-/..|..
.|....-|.\
..//.|....
"#
.into();
assert_eq!(max_visited(&contraption), 51);
}
}

View File

@ -16,7 +16,8 @@ mod day12;
mod day13;
mod day14;
mod day15;
mod day16;
fn main() {
day15::run();
day16::run();
}