Skip to content

Commit 76be42a

Browse files
committed
18th day
1 parent d9dd7ad commit 76be42a

File tree

2 files changed

+157
-0
lines changed

2 files changed

+157
-0
lines changed

data/examples/18.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
5,4
2+
4,2
3+
4,5
4+
3,0
5+
2,1
6+
6,3
7+
2,4
8+
1,5
9+
0,6
10+
3,3
11+
2,6
12+
5,1
13+
1,2
14+
5,5
15+
2,5
16+
6,5
17+
1,4
18+
0,4
19+
6,4
20+
1,1
21+
6,1
22+
1,0
23+
0,5
24+
1,6
25+
2,0
26+
27+
7,7,12

src/bin/18.rs

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
advent_of_code::solution!(18);
2+
3+
use std::collections::VecDeque;
4+
5+
use advent_of_code::maneatingape::grid::*;
6+
use advent_of_code::maneatingape::hash::*;
7+
use advent_of_code::maneatingape::iter::*;
8+
use advent_of_code::maneatingape::parse::*;
9+
use advent_of_code::maneatingape::point::*;
10+
11+
#[derive(Clone)]
12+
enum Block {
13+
Ok,
14+
Corrupted,
15+
}
16+
17+
fn parse_data(input: &str) -> (Vec<Point>, i32, i32, usize) {
18+
let default_right = format!("{},{},{}", 71, 71, 1024);
19+
let (left, right) = input.split_once("\n\n").unwrap_or((input, &default_right));
20+
21+
let data = left
22+
.iter_signed()
23+
.chunk::<2>()
24+
.map(|[x, y]| Point::new(x, y))
25+
.collect();
26+
27+
let [width, height, first_take] = right.iter_signed().chunk::<3>().next().unwrap();
28+
29+
(data, width, height, first_take as usize)
30+
}
31+
32+
fn neighbors(grid: &Grid<Block>, position: Point, cost: u32) -> Vec<(Point, u32)> {
33+
let mut result = Vec::with_capacity(4);
34+
35+
for direction in [LEFT, RIGHT, UP, DOWN] {
36+
let n_position = position + direction;
37+
38+
if grid.contains(n_position) && matches!(grid[n_position], Block::Ok) {
39+
result.push((n_position, cost + 1));
40+
}
41+
}
42+
43+
result
44+
}
45+
46+
fn find_shortest_path_cost(grid: &Grid<Block>) -> u32 {
47+
let start_position = Point::new(0, 0);
48+
let end_position = Point::new(grid.width - 1, grid.height - 1);
49+
50+
let mut queue = VecDeque::new();
51+
let mut g_score = FastMap::new();
52+
53+
queue.push_front((0, start_position));
54+
g_score.insert(start_position, 0);
55+
56+
while let Some((cost, position)) = queue.pop_front() {
57+
if position == end_position {
58+
return cost;
59+
}
60+
61+
for (n_position, n_cost) in neighbors(grid, position, cost) {
62+
if n_cost < *g_score.get(&n_position).unwrap_or(&u32::MAX) {
63+
g_score.insert(n_position, n_cost);
64+
queue.push_back((n_cost, n_position));
65+
}
66+
}
67+
}
68+
69+
u32::MAX
70+
}
71+
72+
fn generate_grid(data: &[Point], width: i32, height: i32, n: usize) -> Grid<Block> {
73+
let mut grid = Grid {
74+
width,
75+
height,
76+
bytes: vec![Block::Ok; (width * height) as usize],
77+
};
78+
79+
data.iter().take(n).for_each(|&point| {
80+
grid[point] = Block::Corrupted;
81+
});
82+
83+
grid
84+
}
85+
86+
pub fn part_one(input: &str) -> Option<u32> {
87+
let (data, width, height, first_take) = parse_data(input);
88+
89+
let result = find_shortest_path_cost(&generate_grid(&data, width, height, first_take));
90+
91+
Some(result)
92+
}
93+
94+
pub fn part_two(input: &str) -> Option<String> {
95+
let (data, width, height, first_take) = parse_data(input);
96+
97+
let mut a = first_take;
98+
let mut b = input.lines().count();
99+
while (b - a) > 1 {
100+
let c = (a + b) / 2;
101+
102+
let result = find_shortest_path_cost(&generate_grid(&data, width, height, c));
103+
if result == u32::MAX {
104+
b = c;
105+
} else {
106+
a = c;
107+
}
108+
}
109+
110+
let result = format!("{},{}", data[a].x, data[a].y);
111+
112+
Some(result)
113+
}
114+
115+
#[cfg(test)]
116+
mod tests {
117+
use super::*;
118+
119+
#[test]
120+
fn test_part_one() {
121+
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
122+
assert_eq!(result, Some(22));
123+
}
124+
125+
#[test]
126+
fn test_part_two() {
127+
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
128+
assert_eq!(result, Some(String::from("6,1")));
129+
}
130+
}

0 commit comments

Comments
 (0)