Skip to content

Commit 8201e63

Browse files
committed
AoC 2024 Day 15 - rust
1 parent 93623e5 commit 8201e63

File tree

4 files changed

+220
-2
lines changed

4 files changed

+220
-2
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
| | 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 |
1010
| ---| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
1111
| 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) | | | | | | | | | | |
12-
| 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)| | | | | | | | | | |
13-
| 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) | | | | | | | | | | | |
12+
| 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) | | | | | | | | | | |
13+
| 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) | | | | | | | | | | |
1414
<!-- @END:ImplementationsTable:2024@ -->
1515

1616
## 2023
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "AoC2024_15"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
aoc = { path = "../aoc" }
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
#![allow(non_snake_case)]
2+
3+
use aoc::geometry::Direction;
4+
use aoc::grid::{Cell, CharGrid, Grid};
5+
use aoc::Puzzle;
6+
use std::collections::{HashMap, VecDeque};
7+
use std::str::FromStr;
8+
9+
struct AoC2024_15;
10+
11+
impl AoC2024_15 {
12+
fn get_grid(&self, lines: &[String]) -> CharGrid {
13+
CharGrid::from(&lines.iter().map(AsRef::as_ref).collect::<Vec<_>>())
14+
}
15+
16+
fn get_wide_grid(&self, lines: &[String]) -> CharGrid {
17+
let mut grid: Vec<String> = vec![];
18+
for line in lines {
19+
let mut row = String::new();
20+
line.chars().for_each(|ch| match ch {
21+
'.' => row.push_str(".."),
22+
'O' => row.push_str("[]"),
23+
'@' => row.push_str("@."),
24+
'#' => row.push_str("##"),
25+
_ => panic!(),
26+
});
27+
grid.push(row);
28+
}
29+
CharGrid::from(&grid.iter().map(AsRef::as_ref).collect::<Vec<_>>())
30+
}
31+
32+
fn solve<F>(
33+
&self,
34+
grid: &mut CharGrid,
35+
dirs: &Vec<Direction>,
36+
get_to_move: F,
37+
) -> usize
38+
where
39+
F: Fn(&CharGrid, Cell, &Direction) -> Vec<Cell>,
40+
{
41+
let mut robot = grid.find_first_matching(|ch| ch == '@').unwrap();
42+
for dir in dirs {
43+
let to_move = get_to_move(grid, robot, dir);
44+
if to_move.is_empty() {
45+
continue;
46+
}
47+
let vals: HashMap<(usize, usize), char> = to_move
48+
.iter()
49+
.map(|cell| ((cell.row, cell.col), grid.get(cell)))
50+
.collect();
51+
robot = robot.try_at(*dir).unwrap();
52+
for cell in to_move.iter() {
53+
grid.get_data_mut()[cell.row][cell.col] = '.';
54+
}
55+
for cell in to_move.iter() {
56+
let nxt = cell.try_at(*dir).unwrap();
57+
grid.get_data_mut()[nxt.row][nxt.col] =
58+
*(vals.get(&(cell.row, cell.col)).unwrap());
59+
}
60+
}
61+
grid.cells()
62+
.filter(|cell| grid.get(cell) == 'O' || grid.get(cell) == '[')
63+
.map(|cell| (cell.row * 100 + cell.col))
64+
.sum()
65+
}
66+
}
67+
68+
impl aoc::Puzzle for AoC2024_15 {
69+
type Input = (Vec<String>, Vec<Direction>);
70+
type Output1 = usize;
71+
type Output2 = usize;
72+
73+
aoc::puzzle_year_day!(2024, 15);
74+
75+
fn parse_input(&self, lines: Vec<String>) -> Self::Input {
76+
let mut dirs: Vec<Direction> = vec![];
77+
let mut blocks = lines.split(|line| line.is_empty());
78+
let grid = blocks.next().unwrap().to_vec();
79+
blocks.next().unwrap().iter().for_each(|line| {
80+
line.chars()
81+
.map(|ch| Direction::from_str(&ch.to_string()).unwrap())
82+
.for_each(|d| dirs.push(d));
83+
});
84+
(grid, dirs)
85+
}
86+
87+
fn part_1(&self, input: &Self::Input) -> Self::Output1 {
88+
let get_to_move = |grid: &CharGrid, robot: Cell, dir: &Direction| {
89+
let mut to_move = vec![robot];
90+
let mut q: VecDeque<Cell> = VecDeque::from(vec![robot]);
91+
while let Some(cell) = q.pop_front() {
92+
let nxt = cell.try_at(*dir).unwrap();
93+
if to_move.contains(&nxt) {
94+
continue;
95+
}
96+
match grid.get(&nxt) {
97+
'#' => return vec![],
98+
'O' => {
99+
to_move.push(nxt);
100+
q.push_back(nxt);
101+
}
102+
_ => continue,
103+
}
104+
}
105+
to_move
106+
};
107+
108+
let (grid, dirs) = input;
109+
self.solve(&mut self.get_grid(grid), dirs, get_to_move)
110+
}
111+
112+
fn part_2(&self, input: &Self::Input) -> Self::Output2 {
113+
let get_to_move = |grid: &CharGrid, robot: Cell, dir: &Direction| {
114+
let mut to_move = vec![robot];
115+
let mut q: VecDeque<Cell> = VecDeque::from(vec![robot]);
116+
while let Some(cell) = q.pop_front() {
117+
let nxt = cell.try_at(*dir).unwrap();
118+
if to_move.contains(&nxt) {
119+
continue;
120+
}
121+
match grid.get(&nxt) {
122+
'#' => return vec![],
123+
'[' => {
124+
let right = nxt.try_at(Direction::Right).unwrap();
125+
to_move.push(nxt);
126+
q.push_back(nxt);
127+
to_move.push(right);
128+
q.push_back(right);
129+
}
130+
']' => {
131+
let left = nxt.try_at(Direction::Left).unwrap();
132+
to_move.push(nxt);
133+
q.push_back(nxt);
134+
to_move.push(left);
135+
q.push_back(left);
136+
}
137+
_ => continue,
138+
}
139+
}
140+
to_move
141+
};
142+
143+
let (grid, dirs) = input;
144+
self.solve(&mut self.get_wide_grid(grid), dirs, get_to_move)
145+
}
146+
147+
fn samples(&self) {
148+
aoc::puzzle_samples! {
149+
self, part_1, TEST1, 2028,
150+
self, part_1, TEST2, 10092,
151+
self, part_2, TEST2, 9021
152+
};
153+
}
154+
}
155+
156+
fn main() {
157+
AoC2024_15 {}.run(std::env::args());
158+
}
159+
160+
const TEST1: &str = "\
161+
########
162+
#..O.O.#
163+
##@.O..#
164+
#...O..#
165+
#.#.O..#
166+
#...O..#
167+
#......#
168+
########
169+
170+
<^^>>>vv<v>>v<<
171+
";
172+
const TEST2: &str = "\
173+
##########
174+
#..O..O.O#
175+
#......O.#
176+
#.OO..O.O#
177+
178+
#O#..O...#
179+
#O..O..O.#
180+
#.OO.O.OO#
181+
#....O...#
182+
##########
183+
184+
<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^
185+
vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v
186+
><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<
187+
<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^
188+
^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><
189+
^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^
190+
>^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^
191+
<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>
192+
^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>
193+
v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^
194+
";
195+
196+
#[cfg(test)]
197+
mod tests {
198+
use super::*;
199+
200+
#[test]
201+
pub fn samples() {
202+
AoC2024_15 {}.samples();
203+
}
204+
}

src/main/rust/Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)