Skip to content

Commit

Permalink
AoC 2024 Day 15 - rust
Browse files Browse the repository at this point in the history
  • Loading branch information
pareronia committed Dec 16, 2024
1 parent 93623e5 commit 8201e63
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 2 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) | | | | | | | | | | |
<!-- @END:ImplementationsTable:2024@ -->

## 2023
Expand Down
7 changes: 7 additions & 0 deletions src/main/rust/AoC2024_15/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "AoC2024_15"
version = "0.1.0"
edition = "2021"

[dependencies]
aoc = { path = "../aoc" }
204 changes: 204 additions & 0 deletions src/main/rust/AoC2024_15/src/main.rs
Original file line number Diff line number Diff line change
@@ -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::<Vec<_>>())
}

fn get_wide_grid(&self, lines: &[String]) -> CharGrid {
let mut grid: Vec<String> = 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::<Vec<_>>())
}

fn solve<F>(
&self,
grid: &mut CharGrid,
dirs: &Vec<Direction>,
get_to_move: F,
) -> usize
where
F: Fn(&CharGrid, Cell, &Direction) -> Vec<Cell>,
{
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<String>, Vec<Direction>);
type Output1 = usize;
type Output2 = usize;

aoc::puzzle_year_day!(2024, 15);

fn parse_input(&self, lines: Vec<String>) -> Self::Input {
let mut dirs: Vec<Direction> = 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<Cell> = 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<Cell> = 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>>v<<
";
const TEST2: &str = "\
##########
#..O..O.O#
#......O.#
#.OO..O.O#
#..O@..O.#
#O#..O...#
#O..O..O.#
#.OO.O.OO#
#....O...#
##########
<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^
vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v
><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<
<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^
^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><
^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^
>^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^
<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>
^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>
v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^
";

#[cfg(test)]
mod tests {
use super::*;

#[test]
pub fn samples() {
AoC2024_15 {}.samples();
}
}
7 changes: 7 additions & 0 deletions src/main/rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 8201e63

Please sign in to comment.