Skip to content

Commit c7b8c9f

Browse files
committed
Rust/2024/18: improve solution
1 parent f9a5663 commit c7b8c9f

File tree

1 file changed

+60
-18
lines changed

1 file changed

+60
-18
lines changed

Rust/2024/18.rs

+60-18
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,33 @@ fn setup(input: &str) -> Input {
4848
}
4949
}
5050

51-
fn bfs(input: &Input, prefix_len: usize) -> Option<usize> {
51+
struct UnionFind {
52+
parents: Vec<usize>,
53+
}
54+
55+
impl UnionFind {
56+
fn new(len: usize) -> Self {
57+
Self {
58+
parents: (0..len).collect(),
59+
}
60+
}
61+
62+
fn find(&mut self, x: usize) -> usize {
63+
if self.parents[x] == x {
64+
return x;
65+
}
66+
self.parents[x] = self.find(self.parents[x]);
67+
self.parents[x]
68+
}
69+
70+
fn merge(&mut self, x: usize, y: usize) {
71+
let x = self.find(x);
72+
let y = self.find(y);
73+
self.parents[x] = y;
74+
}
75+
}
76+
77+
fn part1(input: &Input) -> usize {
5278
let mut queue = VecDeque::from([(0, 0, 0)]);
5379
let mut visited = vec![false; input.width * input.height];
5480
while let Some((d, x, y)) = queue.pop_front() {
@@ -58,37 +84,53 @@ fn bfs(input: &Input, prefix_len: usize) -> Option<usize> {
5884
}
5985

6086
if (x, y) == (input.width - 1, input.height - 1) {
61-
return Some(d);
87+
return d;
6288
}
6389

6490
queue.extend(
6591
Direction::iter()
6692
.flat_map(|d| d.step(x, y, input.width, input.height))
67-
.filter(|&(nx, ny)| input.grid[ny * input.width + nx] >= prefix_len)
93+
.filter(|&(nx, ny)| input.grid[ny * input.width + nx] >= input.prefix_len)
6894
.map(|(nx, ny)| (d + 1, nx, ny)),
6995
);
7096
}
7197

72-
None
73-
}
74-
75-
fn part1(input: &Input) -> usize {
76-
bfs(input, input.prefix_len).unwrap()
98+
panic!()
7799
}
78100

79101
fn part2(input: &Input) -> String {
80-
let mut left = 0;
81-
let mut right = input.bytes.len();
82-
while left + 1 < right {
83-
let m = left.midpoint(right);
84-
match bfs(input, m) {
85-
Some(_) => left = m,
86-
None => right = m,
102+
let mut uf = UnionFind::new(input.width * input.height);
103+
for y in 0..input.height {
104+
for x in 0..input.width {
105+
let idx = y * input.width + x;
106+
if x + 1 < input.width
107+
&& input.grid[idx] == usize::MAX
108+
&& input.grid[idx + 1] == usize::MAX
109+
{
110+
uf.merge(idx, idx + 1);
111+
}
112+
if y + 1 < input.height
113+
&& input.grid[idx] == usize::MAX
114+
&& input.grid[idx + input.width] == usize::MAX
115+
{
116+
uf.merge(idx, idx + input.width);
117+
}
87118
}
88119
}
89-
debug_assert_eq!(left + 1, right);
90-
let (x, y) = input.bytes[right - 1];
91-
format!("{x},{y}")
120+
121+
for (i, &(x, y)) in input.bytes.iter().enumerate().rev() {
122+
for (nx, ny) in Direction::iter()
123+
.flat_map(|d| d.step(x, y, input.width, input.height))
124+
.filter(|&(nx, ny)| input.grid[ny * input.width + nx] > i)
125+
{
126+
uf.merge(y * input.width + x, ny * input.width + nx);
127+
}
128+
if uf.find(0) == uf.find(input.width * input.height - 1) {
129+
return format!("{x},{y}");
130+
}
131+
}
132+
133+
panic!()
92134
}
93135

94136
aoc::main!(2024, 18, ex: 1);

0 commit comments

Comments
 (0)