From 8201e63bcac1478274dd07c7925c41bb6533bee9 Mon Sep 17 00:00:00 2001 From: pareronia <49491686+pareronia@users.noreply.github.com> Date: Mon, 16 Dec 2024 02:37:32 +0100 Subject: [PATCH] AoC 2024 Day 15 - rust --- README.md | 4 +- src/main/rust/AoC2024_15/Cargo.toml | 7 + src/main/rust/AoC2024_15/src/main.rs | 204 +++++++++++++++++++++++++++ src/main/rust/Cargo.lock | 7 + 4 files changed, 220 insertions(+), 2 deletions(-) create mode 100644 src/main/rust/AoC2024_15/Cargo.toml create mode 100644 src/main/rust/AoC2024_15/src/main.rs diff --git a/README.md b/README.md index 51679a8..3d2ea4b 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | | ---| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | python3 | [✓](src/main/python/AoC2024_01.py) | [✓](src/main/python/AoC2024_02.py) | [✓](src/main/python/AoC2024_03.py) | [✓](src/main/python/AoC2024_04.py) | [✓](src/main/python/AoC2024_05.py) | [✓](src/main/python/AoC2024_06.py) | [✓](src/main/python/AoC2024_07.py) | [✓](src/main/python/AoC2024_08.py) | [✓](src/main/python/AoC2024_09.py) | [✓](src/main/python/AoC2024_10.py) | [✓](src/main/python/AoC2024_11.py) | [✓](src/main/python/AoC2024_12.py) | [✓](src/main/python/AoC2024_13.py) | [✓](src/main/python/AoC2024_14.py) | [✓](src/main/python/AoC2024_15.py) | | | | | | | | | | | -| java | [✓](src/main/java/AoC2024_01.java) | [✓](src/main/java/AoC2024_02.java) | [✓](src/main/java/AoC2024_03.java) | [✓](src/main/java/AoC2024_04.java) | [✓](src/main/java/AoC2024_05.java) | [✓](src/main/java/AoC2024_06.java) | [✓](src/main/java/AoC2024_07.java) | [✓](src/main/java/AoC2024_08.java) | | [✓](src/main/java/AoC2024_10.java) | [✓](src/main/java/AoC2024_11.java) | [✓](src/main/java/AoC2024_12.java) | | [✓](src/main/java/AoC2024_14.java) | [✓](src/main/java/AoC2024_15.java)| | | | | | | | | | | -| rust | [✓](src/main/rust/AoC2024_01/src/main.rs) | [✓](src/main/rust/AoC2024_02/src/main.rs) | [✓](src/main/rust/AoC2024_03/src/main.rs) | [✓](src/main/rust/AoC2024_04/src/main.rs) | [✓](src/main/rust/AoC2024_05/src/main.rs) | [✓](src/main/rust/AoC2024_06/src/main.rs) | [✓](src/main/rust/AoC2024_07/src/main.rs) | [✓](src/main/rust/AoC2024_08/src/main.rs) | | [✓](src/main/rust/AoC2024_10/src/main.rs) | | | [✓](src/main/rust/AoC2024_13/src/main.rs) | [✓](src/main/rust/AoC2024_14/src/main.rs) | | | | | | | | | | | | +| java | [✓](src/main/java/AoC2024_01.java) | [✓](src/main/java/AoC2024_02.java) | [✓](src/main/java/AoC2024_03.java) | [✓](src/main/java/AoC2024_04.java) | [✓](src/main/java/AoC2024_05.java) | [✓](src/main/java/AoC2024_06.java) | [✓](src/main/java/AoC2024_07.java) | [✓](src/main/java/AoC2024_08.java) | | [✓](src/main/java/AoC2024_10.java) | [✓](src/main/java/AoC2024_11.java) | [✓](src/main/java/AoC2024_12.java) | | [✓](src/main/java/AoC2024_14.java) | [✓](src/main/java/AoC2024_15.java) | | | | | | | | | | | +| rust | [✓](src/main/rust/AoC2024_01/src/main.rs) | [✓](src/main/rust/AoC2024_02/src/main.rs) | [✓](src/main/rust/AoC2024_03/src/main.rs) | [✓](src/main/rust/AoC2024_04/src/main.rs) | [✓](src/main/rust/AoC2024_05/src/main.rs) | [✓](src/main/rust/AoC2024_06/src/main.rs) | [✓](src/main/rust/AoC2024_07/src/main.rs) | [✓](src/main/rust/AoC2024_08/src/main.rs) | | [✓](src/main/rust/AoC2024_10/src/main.rs) | | | [✓](src/main/rust/AoC2024_13/src/main.rs) | [✓](src/main/rust/AoC2024_14/src/main.rs) | [✓](src/main/rust/AoC2024_15/src/main.rs) | | | | | | | | | | | ## 2023 diff --git a/src/main/rust/AoC2024_15/Cargo.toml b/src/main/rust/AoC2024_15/Cargo.toml new file mode 100644 index 0000000..bcf6804 --- /dev/null +++ b/src/main/rust/AoC2024_15/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "AoC2024_15" +version = "0.1.0" +edition = "2021" + +[dependencies] +aoc = { path = "../aoc" } diff --git a/src/main/rust/AoC2024_15/src/main.rs b/src/main/rust/AoC2024_15/src/main.rs new file mode 100644 index 0000000..c72684b --- /dev/null +++ b/src/main/rust/AoC2024_15/src/main.rs @@ -0,0 +1,204 @@ +#![allow(non_snake_case)] + +use aoc::geometry::Direction; +use aoc::grid::{Cell, CharGrid, Grid}; +use aoc::Puzzle; +use std::collections::{HashMap, VecDeque}; +use std::str::FromStr; + +struct AoC2024_15; + +impl AoC2024_15 { + fn get_grid(&self, lines: &[String]) -> CharGrid { + CharGrid::from(&lines.iter().map(AsRef::as_ref).collect::>()) + } + + fn get_wide_grid(&self, lines: &[String]) -> CharGrid { + let mut grid: Vec = vec![]; + for line in lines { + let mut row = String::new(); + line.chars().for_each(|ch| match ch { + '.' => row.push_str(".."), + 'O' => row.push_str("[]"), + '@' => row.push_str("@."), + '#' => row.push_str("##"), + _ => panic!(), + }); + grid.push(row); + } + CharGrid::from(&grid.iter().map(AsRef::as_ref).collect::>()) + } + + fn solve( + &self, + grid: &mut CharGrid, + dirs: &Vec, + get_to_move: F, + ) -> usize + where + F: Fn(&CharGrid, Cell, &Direction) -> Vec, + { + let mut robot = grid.find_first_matching(|ch| ch == '@').unwrap(); + for dir in dirs { + let to_move = get_to_move(grid, robot, dir); + if to_move.is_empty() { + continue; + } + let vals: HashMap<(usize, usize), char> = to_move + .iter() + .map(|cell| ((cell.row, cell.col), grid.get(cell))) + .collect(); + robot = robot.try_at(*dir).unwrap(); + for cell in to_move.iter() { + grid.get_data_mut()[cell.row][cell.col] = '.'; + } + for cell in to_move.iter() { + let nxt = cell.try_at(*dir).unwrap(); + grid.get_data_mut()[nxt.row][nxt.col] = + *(vals.get(&(cell.row, cell.col)).unwrap()); + } + } + grid.cells() + .filter(|cell| grid.get(cell) == 'O' || grid.get(cell) == '[') + .map(|cell| (cell.row * 100 + cell.col)) + .sum() + } +} + +impl aoc::Puzzle for AoC2024_15 { + type Input = (Vec, Vec); + type Output1 = usize; + type Output2 = usize; + + aoc::puzzle_year_day!(2024, 15); + + fn parse_input(&self, lines: Vec) -> Self::Input { + let mut dirs: Vec = vec![]; + let mut blocks = lines.split(|line| line.is_empty()); + let grid = blocks.next().unwrap().to_vec(); + blocks.next().unwrap().iter().for_each(|line| { + line.chars() + .map(|ch| Direction::from_str(&ch.to_string()).unwrap()) + .for_each(|d| dirs.push(d)); + }); + (grid, dirs) + } + + fn part_1(&self, input: &Self::Input) -> Self::Output1 { + let get_to_move = |grid: &CharGrid, robot: Cell, dir: &Direction| { + let mut to_move = vec![robot]; + let mut q: VecDeque = VecDeque::from(vec![robot]); + while let Some(cell) = q.pop_front() { + let nxt = cell.try_at(*dir).unwrap(); + if to_move.contains(&nxt) { + continue; + } + match grid.get(&nxt) { + '#' => return vec![], + 'O' => { + to_move.push(nxt); + q.push_back(nxt); + } + _ => continue, + } + } + to_move + }; + + let (grid, dirs) = input; + self.solve(&mut self.get_grid(grid), dirs, get_to_move) + } + + fn part_2(&self, input: &Self::Input) -> Self::Output2 { + let get_to_move = |grid: &CharGrid, robot: Cell, dir: &Direction| { + let mut to_move = vec![robot]; + let mut q: VecDeque = VecDeque::from(vec![robot]); + while let Some(cell) = q.pop_front() { + let nxt = cell.try_at(*dir).unwrap(); + if to_move.contains(&nxt) { + continue; + } + match grid.get(&nxt) { + '#' => return vec![], + '[' => { + let right = nxt.try_at(Direction::Right).unwrap(); + to_move.push(nxt); + q.push_back(nxt); + to_move.push(right); + q.push_back(right); + } + ']' => { + let left = nxt.try_at(Direction::Left).unwrap(); + to_move.push(nxt); + q.push_back(nxt); + to_move.push(left); + q.push_back(left); + } + _ => continue, + } + } + to_move + }; + + let (grid, dirs) = input; + self.solve(&mut self.get_wide_grid(grid), dirs, get_to_move) + } + + fn samples(&self) { + aoc::puzzle_samples! { + self, part_1, TEST1, 2028, + self, part_1, TEST2, 10092, + self, part_2, TEST2, 9021 + }; + } +} + +fn main() { + AoC2024_15 {}.run(std::env::args()); +} + +const TEST1: &str = "\ +######## +#..O.O.# +##@.O..# +#...O..# +#.#.O..# +#...O..# +#......# +######## + +<^^>>>vv>v<< +"; +const TEST2: &str = "\ +########## +#..O..O.O# +#......O.# +#.OO..O.O# +#..O@..O.# +#O#..O...# +#O..O..O.# +#.OO.O.OO# +#....O...# +########## + +^v>^vv^v>v<>v^v<<><>>v^v^>^<<<><^ +vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<^<^^>>>^<>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^v^^<^^vv< +<>^^^^>>>v^<>vvv^>^^^vv^^>v<^^^^v<>^>vvvv><>>v^<<^^^^^ +^><^><>>><>^^<<^^v>>><^^>v>>>^v><>^v><<<>vvvv>^<><<>^>< +^>><>^v<><^vvv<^^<><^v<<<><<<^^<^>>^<<<^>>^v^>>^v>vv>^<<^v<>><<><<>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^ +<><^^>^^^<>^vv<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<> +^^>vv<^v^v^<>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<>< +v^^>>><<^^<>>^v^v^<<>^<^v^v><^<<<><<^vv>>v>v^<<^ +"; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + pub fn samples() { + AoC2024_15 {}.samples(); + } +} diff --git a/src/main/rust/Cargo.lock b/src/main/rust/Cargo.lock index 2d9a8f0..8bff331 100644 --- a/src/main/rust/Cargo.lock +++ b/src/main/rust/Cargo.lock @@ -470,6 +470,13 @@ dependencies = [ "aoc", ] +[[package]] +name = "AoC2024_15" +version = "0.1.0" +dependencies = [ + "aoc", +] + [[package]] name = "aho-corasick" version = "1.0.2"