Skip to content

Commit 91fe2c4

Browse files
committed
[2024] Day 20 initial solution
1 parent 04fd360 commit 91fe2c4

File tree

3 files changed

+124
-0
lines changed

3 files changed

+124
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Thank you to [Eric Wastl](http://was.tl) for running this incredible yearly even
2424
- [Day 17: Chronospatial Computer](aoc_2024/src/day_17.rs)
2525
- [Day 18: RAM Run](aoc_2024/src/day_18.rs)
2626
- [Day 19: Linen Layout](aoc_2024/src/day_19.rs)
27+
- [Day 20: Race Condition](aoc_2024/src/day_20.rs)
2728
<!-- MARKER -->
2829

2930
## [2023](https://adventofcode.com/2023) [![aoc_2023](https://github.com/connorslade/advent-of-code/actions/workflows/aoc_2023.yml/badge.svg)](https://github.com/connorslade/advent-of-code/actions/workflows/aoc_2023.yml)

aoc_2024/src/day_20.rs

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
use std::{collections::VecDeque, convert::identity, u32};
2+
3+
use aoc_lib::{direction::cardinal::Direction, matrix::Grid};
4+
use common::{solution, Answer};
5+
use itertools::Itertools;
6+
use nd_vec::{vector, Vec2};
7+
8+
solution!("Race Condition", 20);
9+
10+
fn part_a(input: &str) -> Answer {
11+
Problem::parse(input).solve(2).into()
12+
}
13+
14+
fn part_b(input: &str) -> Answer {
15+
Problem::parse(input).solve(20).into()
16+
}
17+
18+
struct Problem {
19+
board: Grid<char>,
20+
start: Vec2<usize>,
21+
end: Vec2<usize>,
22+
}
23+
24+
impl Problem {
25+
fn parse(input: &str) -> Self {
26+
let board = Grid::parse(input, identity);
27+
28+
let start = board.find('S').unwrap();
29+
let end = board.find('E').unwrap();
30+
31+
Self { board, start, end }
32+
}
33+
34+
fn solve(&self, max_skip: i32) -> u32 {
35+
let (sc, ec) = (self.cost_map(self.start), self.cost_map(self.end));
36+
let base_cost = sc[self.end];
37+
38+
let mut out = 0;
39+
40+
for (pos, tile) in self.board.iter() {
41+
if *tile == '#' || sc[pos] == u32::MAX {
42+
continue;
43+
}
44+
45+
for (x, y) in (-max_skip..=max_skip).cartesian_product(-max_skip..=max_skip) {
46+
let offset = vector!(x, y);
47+
let dist = offset.manhattan_distance(&Vec2::zero());
48+
if dist > max_skip {
49+
continue;
50+
}
51+
52+
let end = pos.try_cast::<i32>().unwrap() + offset;
53+
if !self.board.contains(end) || self.board[end] == '#' || ec[end] == u32::MAX {
54+
continue;
55+
}
56+
57+
let cost = sc[pos] + ec[end] + dist as u32;
58+
out += (cost + 100 <= base_cost) as u32;
59+
}
60+
}
61+
62+
out
63+
}
64+
65+
fn cost_map(&self, start: Vec2<usize>) -> Grid<u32> {
66+
let mut costs = Grid::new(self.board.size, u32::MAX);
67+
let mut queue = VecDeque::new();
68+
queue.push_back((start, 0));
69+
70+
while let Some((pos, dist)) = queue.pop_front() {
71+
if costs[pos] != u32::MAX {
72+
continue;
73+
}
74+
75+
costs[pos] = dist;
76+
for dir in Direction::ALL {
77+
let next = dir.wrapping_advance(pos);
78+
if let Some(tile) = self.board.get(next) {
79+
if matches!(tile, '.' | 'E') {
80+
queue.push_back((next, dist + 1));
81+
}
82+
}
83+
}
84+
}
85+
86+
costs
87+
}
88+
}
89+
90+
#[cfg(test)]
91+
mod test {
92+
use indoc::indoc;
93+
94+
const CASE: &str = indoc! {"
95+
###############
96+
#...#...#.....#
97+
#.#.#.#.#.###.#
98+
#S#...#.#.#...#
99+
#######.#.#.###
100+
#######.#.#...#
101+
#######.#.###.#
102+
###..E#...#...#
103+
###.#######.###
104+
#...###...#...#
105+
#.#####.#.###.#
106+
#.#...#.#.#...#
107+
#.#.#.#.#.#.###
108+
#...#...#...###
109+
###############
110+
"};
111+
112+
#[test]
113+
fn part_a() {
114+
assert_eq!(super::part_a(CASE), 44.into());
115+
}
116+
117+
#[test]
118+
fn part_b() {
119+
assert_eq!(super::part_b(CASE), ().into());
120+
}
121+
}

aoc_2024/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ mod day_16;
1919
mod day_17;
2020
mod day_18;
2121
mod day_19;
22+
mod day_20;
2223
// [import_marker]
2324

2425
pub const SOLUTIONS: &[Solution] = &[
@@ -41,5 +42,6 @@ pub const SOLUTIONS: &[Solution] = &[
4142
day_17::SOLUTION,
4243
day_18::SOLUTION,
4344
day_19::SOLUTION,
45+
day_20::SOLUTION,
4446
// [list_marker]
4547
];

0 commit comments

Comments
 (0)