From 8447f2ddc5505d474de4b535f619599e9ac58ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20H=C3=B6lting?= <87192362+moritz-hoelting@users.noreply.github.com> Date: Sat, 16 Dec 2023 21:20:25 +0100 Subject: [PATCH] day 16 --- Cargo.lock | 8 ++ day-16/Cargo.toml | 12 +++ day-16/src/bin/input.txt | 110 ++++++++++++++++++++++++++ day-16/src/bin/part1.rs | 151 +++++++++++++++++++++++++++++++++++ day-16/src/bin/part2.rs | 165 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 446 insertions(+) create mode 100644 day-16/Cargo.toml create mode 100644 day-16/src/bin/input.txt create mode 100644 day-16/src/bin/part1.rs create mode 100644 day-16/src/bin/part2.rs diff --git a/Cargo.lock b/Cargo.lock index eb7f8fe..6c24683 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -166,6 +166,14 @@ dependencies = [ "indoc", ] +[[package]] +name = "day-16" +version = "0.0.0" +dependencies = [ + "indoc", + "rayon", +] + [[package]] name = "deprecate-until" version = "0.1.1" diff --git a/day-16/Cargo.toml b/day-16/Cargo.toml new file mode 100644 index 0000000..07ec878 --- /dev/null +++ b/day-16/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "day-16" +version = "0.0.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rayon.workspace = true + +[dev-dependencies] +indoc.workspace = true diff --git a/day-16/src/bin/input.txt b/day-16/src/bin/input.txt new file mode 100644 index 0000000..b335246 --- /dev/null +++ b/day-16/src/bin/input.txt @@ -0,0 +1,110 @@ +\\.........../..............-..../....\.......\.................|....|..........|............-\.....|......... +................................../.......|..\..........-....................\........../../\../.............. +.............................|...|.............\..\.....|.........\....................../............/-...... +\................\.............|..../........\\.....\\........-.........../..\.../...\.......\/.......|..|.... +......\..............|...|..../........-../.................../....|./................./.\........\.|-........ +.............................-....................-............/.\............../........\/........|...\...... +./........|................\.|........\.......\../.-.........\..-.............|............................... +|....................|...............-/............-.|..|...........................|..................\...... +................../........\../...........|..................\................./.......\...-......../|........ +././...........-..|....................................-.....................|./........../..|.-..\..|.....|.. +.............|.......................||................................../..-........./.................../... +........-......\............/.....-...\..|...........\..........-.........................\................... +\/...............\.|......................\......\.........\/..........\................./.-.../...-.....|.... +....\........................................................\.......-/.............\/.........\.............. +\........\.........\..\..|....\..............-...../.................|.....|.................\.-/............. +.............................\/..-..............\....-...-............................................./...... +....|..../...................//.........\.............\......|...|....../............|.......-.|.-.-|.......\. +.........|..-.-........\\../...........|.....\............................../....\\..\......../......\\..|.... +.......|....................-...././...../.|../........................./...-\...|.......|.......-....|......\ +../.../........-......................|......-.....\..............-../.......|./.......|.............|.......| +........................................................./............-......\.../........\../../.........\... +........................./../.../............-.\.........................|..............|....................| +..-......./.--.......|.............................................\........\.........\...............\......| +.|........................................|..........-....\.......\.......|................................../ +..............................................\.....\........|.....\./......\................|......../...../. +./.\......../..\\..|....-.-|..-.............................................../.\|/........\.........-|...|... +........|........-.\/................-.........-............../.|..........\./|...--...............|.......... +.................-............./././...........|.|.....|....|......\-....|...............|.................... +.......././..............................................|/...\........../......./..||.\..-................... +............-..|....................\..-./.........\.......................................................... +./.-...............\......\...|......\....../..........................-....................-...|......\...... +.....././...-........................\..../..|-.............../.......................................\|...... +-.........................................../...............-....../.....|.........\..-.........|............. +....|.......\....\|.....\.|....|.............\..\...-............../.....................\....-............... +.............-..-..................\..............|..|........................-..........\../.\......../...... +.....|.....................\.....\.......\...........\....|.........\.......//.................|........./.... +|.....\-/.......|............../.....\..........|......./......./...............\./..........|................ +............../|.......................|....../..............-...................-...................../...... +../|....\.......\...............\................-........\..../../.................\/.........\....\......... +........-.....|.|......-...........\............|...................\...........|.......................|..... +.....|....|..\..........................|................\..../....-..................................|....... +..-........||/................/........|......................-....-..................../..|...../............ +............./.............\..-.......................\..................||.-.-..|...............\...|...\.... +............................\....\....../....\...........-...................|....-.....|..................... +.../...........................-..|.....|../.........\./.................\|..............||....|..........\... +.................../........\...........\........../............|...|\....\........|......-...\.......|./...\. +-....|...........\............./..\...........||...................|.............../...............\.......... +.........\.........-..................../.../.......//.............-/...-.-|....\............................. +..-.........\......././................-.........|-...../............|....-.............\..................... +......../.......|.............................\....|......................../................................- +..\........./.--................/................................................................../......-... +.../................|.\....-.................................\.../....................................\....... +.............................\....../.|...........-............................................/....-......... +...\./..........-........./../...............................-..-........-....../..................-.....\.... +.........\........./\........................-.-................................|............................. +..../.|-.................................-............\..................|.........|......./......-........... +.-|..........................-........|...//..\.../.........-............/|.............|..............-..\... +..../......|...\..........|...........-.||....-..|.........-......../..........|................../........... +\.../../............./../...........\...........\.......................................\./.............|..... +.....|.../....|..............................\........\...................|.........|......................... +..........|............|............./......../.../................................-.....-.........../..|..... +......-.\.........................|...../.....\.....-/....-..|.\.........\|....-.........||...........\....... +..\......\............./...............\-............/...|................................/................... +.......|.|...|.|.........|..|.......-...\.........|./..|..................-................|..........-....... +..-\...--..-........|......................-.....|./..............|/.................../...........\....-.../. +...........-...-........-..........-...........|.......-................\.........|............-.............| +.....|.\..-../....\.................../-....\.............|......../....\/.\..\...//..........|............... +......-.-.|..|............................./.........-....|.......|......|..............................-...-. +..|............\...|................./\...|........../...-.|.........\..../.........|-...|.......\...........- +...................\..../..............|...../.....\....../.................\..|.....................-........ +.|............-................../........-.....|..../..........................|../..\.....\....|............ +.............................................|..........|......-\.............-..-........................\... +............./.-....|......|................................................-/|/...|../...........-...|....... +......-................-..-...............|................-.-.............\........|...-./................-.. +...........|...........-/........../..................../|.|...................|...................../........ +.....................................\......................../...........|-...........-................../... +...|.....\.....-...../..............|.........\....\............-\............\/.........................-.... +..............-\......-.............../...|.........................................|.....\/.................. +.................|...|.....|.............../....\...............-....\..........|.-........|........../...|... +..|...-.........\....-.....\.....................|...|.......-....\....-..-......-.\../........-../........... +.......\.....\................\......\-................................|..\.....//.........../..........\..... +........................../.-.................................\--......../..-................................. +.................|............|\./....|.|..|.............//......./.......................|.....\.....\\...... +./...|\...................................../.......................\.........|..............|....|....\...... +......|.............................................................\..|.................\-..../......./...... +.....-.......|........../......./..\...........|...........-..|......../...../................\......\........ +............\....-........\......./.......-...........................................\........-/./........... +|..................................-.........\/..-....././.....\.............../-....................\........ +../.........-..........-....-...-.........\/....................../.../.....\............................-.\.| +........../...-..-........................-........................................./....\.....-.............. +..|-.\........\....................\.\..........-....|.-.-...........\..............\..-.....|................ +..-.../......./\.\...\\.//.....|..........................\........|.-||......................|.......\/...... +...-........-/.............................-......................-|....\...|..../..|.........\............... +.........|..|/........./.......\....\../\.-..-...\..|...../...........\.............../..................../\. +.........\.-\|..|../...........--..........|-......|...|.................||................................... +..................\.....\...........................|.............\..|.........................|...........\.. +....|../........../.............................|./........\\.....|.....|...................................|. +-..........................................-........................-...\..................\.....\......-..... +..\.\......|......|........|.............-|....-.....-...........|../.-.........|........\..\...-...\........\ +.|.......-..|....|..............|.................../...............|.............................-.........// +....................\..\.||./\.......-.........-..-................../..../....................-/..........\.. +.........\.........|...-.....\..........\.\....|.|..............|..........................................\.| +...|\..|................-/..........|\....\/|..-...........................................\.................. +.../...\.|..............................\.-...\.........\....../../...............-./............/............ +.....-.\..............................................\.|....................\..........|...............|..... +.....|................../|....-....-....\..../...............\.....|..|......./.................../........\.. +.......................\....................-.......-.................../..............-...\..\........|...... +...../................\........../..|.../...........|........|............\........-....-/.....\....|......... +.\\.\............|..................................................|......\/..........................\...... +....|........../...../...-.................|......|..........-....................................../.../..... \ No newline at end of file diff --git a/day-16/src/bin/part1.rs b/day-16/src/bin/part1.rs new file mode 100644 index 0000000..377a32f --- /dev/null +++ b/day-16/src/bin/part1.rs @@ -0,0 +1,151 @@ +use std::{collections::HashSet, iter}; + +fn main() { + println!("{}", part1(include_str!("./input.txt"))); +} + +fn part1(input: &str) -> usize { + let grid = input + .lines() + .map(|line| { + line.chars() + .map(|c| Tile::try_from(c).expect("invalid char")) + .collect() + }) + .collect::>>(); + + let mut energized = HashSet::new(); + + let start = vec![(0, 0, Direction::Right)]; + + let _ = iter::successors(Some(start), |curs| { + let next = curs + .iter() + .flat_map(|cur| { + if energized.contains(cur) { + Vec::new() + } else { + energized.insert(*cur); + successors(*cur, &grid) + } + }) + .collect::>(); + (!next.is_empty()).then_some(next) + }) + .collect::>(); + + energized + .into_iter() + .map(|(x, y, _)| (x, y)) + .collect::>() + .len() +} + +fn successors( + (x, y, direction): (usize, usize, Direction), + grid: &Vec>, +) -> Vec<(usize, usize, Direction)> { + let prev = grid[y][x]; + let above = y.checked_sub(1).map(|y| (x, y)); + let below = (y + 1 < grid.len()).then_some((x, y + 1)); + let left = x.checked_sub(1).map(|x| (x, y)); + let right = (x + 1 < grid[0].len()).then_some((x + 1, y)); + + match prev { + Tile::Empty => match direction { + Direction::Up => vec![above.map(|(x, y)| (x, y, Direction::Up))], + Direction::Down => vec![below.map(|(x, y)| (x, y, Direction::Down))], + Direction::Left => vec![left.map(|(x, y)| (x, y, Direction::Left))], + Direction::Right => vec![right.map(|(x, y)| (x, y, Direction::Right))], + }, + Tile::MirrorForward => match direction { + Direction::Up => vec![right.map(|(x, y)| (x, y, Direction::Right))], + Direction::Down => vec![left.map(|(x, y)| (x, y, Direction::Left))], + Direction::Left => vec![below.map(|(x, y)| (x, y, Direction::Down))], + Direction::Right => vec![above.map(|(x, y)| (x, y, Direction::Up))], + }, + Tile::MirrorBackward => match direction { + Direction::Up => vec![left.map(|(x, y)| (x, y, Direction::Left))], + Direction::Down => vec![right.map(|(x, y)| (x, y, Direction::Right))], + Direction::Left => vec![above.map(|(x, y)| (x, y, Direction::Up))], + Direction::Right => vec![below.map(|(x, y)| (x, y, Direction::Down))], + }, + Tile::SplitHorizontal => match direction { + Direction::Up | Direction::Down => vec![ + left.map(|(x, y)| (x, y, Direction::Left)), + right.map(|(x, y)| (x, y, Direction::Right)), + ], + Direction::Left => vec![left.map(|(x, y)| (x, y, Direction::Left))], + Direction::Right => vec![right.map(|(x, y)| (x, y, Direction::Right))], + }, + Tile::SplitVertical => match direction { + Direction::Left | Direction::Right => vec![ + above.map(|(x, y)| (x, y, Direction::Up)), + below.map(|(x, y)| (x, y, Direction::Down)), + ], + Direction::Up => vec![above.map(|(x, y)| (x, y, Direction::Up))], + Direction::Down => vec![below.map(|(x, y)| (x, y, Direction::Down))], + }, + } + .into_iter() + .flatten() + .collect() +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +enum Direction { + Up, + Down, + Left, + Right, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum Tile { + Empty, + SplitHorizontal, + SplitVertical, + MirrorForward, + MirrorBackward, +} +impl TryFrom for Tile { + type Error = (); + + fn try_from(value: char) -> Result { + match value { + '.' => Ok(Self::Empty), + '|' => Ok(Self::SplitVertical), + '-' => Ok(Self::SplitHorizontal), + '/' => Ok(Self::MirrorForward), + '\\' => Ok(Self::MirrorBackward), + _ => Err(()), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use indoc::indoc; + + #[test] + fn test_part1() { + assert_eq!( + part1(indoc!( + r" + .|...\.... + |.-.\..... + .....|-... + ........|. + .......... + .........\ + ..../.\\.. + .-.-/..|.. + .|....-|.\ + ..//.|.... + " + )), + 46 + ); + } +} diff --git a/day-16/src/bin/part2.rs b/day-16/src/bin/part2.rs new file mode 100644 index 0000000..2b0f8e3 --- /dev/null +++ b/day-16/src/bin/part2.rs @@ -0,0 +1,165 @@ +use std::{collections::HashSet, iter}; + +fn main() { + println!("{}", part2(include_str!("./input.txt"))); +} + +fn part2(input: &str) -> usize { + let grid = input + .lines() + .map(|line| { + line.chars() + .map(|c| Tile::try_from(c).expect("invalid char")) + .collect() + }) + .collect::>>(); + + let start_left = (0..grid.len()).map(|y| (0, y, Direction::Right)); + let start_right = (0..grid.len()).map(|y| (grid[0].len() - 1, y, Direction::Left)); + let start_top = (0..grid[0].len()).map(|x| (x, 0, Direction::Down)); + let start_bottom = (0..grid[0].len()).map(|x| (x, grid.len() - 1, Direction::Up)); + + let start_options = start_left + .chain(start_right) + .chain(start_top) + .chain(start_bottom) + .collect::>(); + + start_options + .into_iter() + .map(|start| { + let mut energized = HashSet::new(); + let _ = iter::successors(Some(vec![start]), |curs| { + let next = curs + .iter() + .flat_map(|cur| { + if energized.contains(cur) { + Vec::new() + } else { + energized.insert(*cur); + successors(*cur, &grid) + } + }) + .collect::>(); + (!next.is_empty()).then_some(next) + }) + .collect::>(); + + energized + .into_iter() + .map(|(x, y, _)| (x, y)) + .collect::>() + .len() + }) + .max() + .expect("no maximum") +} + +fn successors( + (x, y, direction): (usize, usize, Direction), + grid: &Vec>, +) -> Vec<(usize, usize, Direction)> { + let prev = grid[y][x]; + let above = y.checked_sub(1).map(|y| (x, y)); + let below = (y + 1 < grid.len()).then_some((x, y + 1)); + let left = x.checked_sub(1).map(|x| (x, y)); + let right = (x + 1 < grid[0].len()).then_some((x + 1, y)); + + match prev { + Tile::Empty => match direction { + Direction::Up => vec![above.map(|(x, y)| (x, y, Direction::Up))], + Direction::Down => vec![below.map(|(x, y)| (x, y, Direction::Down))], + Direction::Left => vec![left.map(|(x, y)| (x, y, Direction::Left))], + Direction::Right => vec![right.map(|(x, y)| (x, y, Direction::Right))], + }, + Tile::MirrorForward => match direction { + Direction::Up => vec![right.map(|(x, y)| (x, y, Direction::Right))], + Direction::Down => vec![left.map(|(x, y)| (x, y, Direction::Left))], + Direction::Left => vec![below.map(|(x, y)| (x, y, Direction::Down))], + Direction::Right => vec![above.map(|(x, y)| (x, y, Direction::Up))], + }, + Tile::MirrorBackward => match direction { + Direction::Up => vec![left.map(|(x, y)| (x, y, Direction::Left))], + Direction::Down => vec![right.map(|(x, y)| (x, y, Direction::Right))], + Direction::Left => vec![above.map(|(x, y)| (x, y, Direction::Up))], + Direction::Right => vec![below.map(|(x, y)| (x, y, Direction::Down))], + }, + Tile::SplitHorizontal => match direction { + Direction::Up | Direction::Down => vec![ + left.map(|(x, y)| (x, y, Direction::Left)), + right.map(|(x, y)| (x, y, Direction::Right)), + ], + Direction::Left => vec![left.map(|(x, y)| (x, y, Direction::Left))], + Direction::Right => vec![right.map(|(x, y)| (x, y, Direction::Right))], + }, + Tile::SplitVertical => match direction { + Direction::Left | Direction::Right => vec![ + above.map(|(x, y)| (x, y, Direction::Up)), + below.map(|(x, y)| (x, y, Direction::Down)), + ], + Direction::Up => vec![above.map(|(x, y)| (x, y, Direction::Up))], + Direction::Down => vec![below.map(|(x, y)| (x, y, Direction::Down))], + }, + } + .into_iter() + .flatten() + .collect() +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +enum Direction { + Up, + Down, + Left, + Right, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum Tile { + Empty, + SplitHorizontal, + SplitVertical, + MirrorForward, + MirrorBackward, +} +impl TryFrom for Tile { + type Error = (); + + fn try_from(value: char) -> Result { + match value { + '.' => Ok(Self::Empty), + '|' => Ok(Self::SplitVertical), + '-' => Ok(Self::SplitHorizontal), + '/' => Ok(Self::MirrorForward), + '\\' => Ok(Self::MirrorBackward), + _ => Err(()), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use indoc::indoc; + + #[test] + fn test_part2() { + assert_eq!( + part2(indoc!( + r" + .|...\.... + |.-.\..... + .....|-... + ........|. + .......... + .........\ + ..../.\\.. + .-.-/..|.. + .|....-|.\ + ..//.|.... + " + )), + 51 + ); + } +}