@@ -48,7 +48,33 @@ fn setup(input: &str) -> Input {
48
48
}
49
49
}
50
50
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 {
52
78
let mut queue = VecDeque :: from ( [ ( 0 , 0 , 0 ) ] ) ;
53
79
let mut visited = vec ! [ false ; input. width * input. height] ;
54
80
while let Some ( ( d, x, y) ) = queue. pop_front ( ) {
@@ -58,37 +84,53 @@ fn bfs(input: &Input, prefix_len: usize) -> Option<usize> {
58
84
}
59
85
60
86
if ( x, y) == ( input. width - 1 , input. height - 1 ) {
61
- return Some ( d ) ;
87
+ return d ;
62
88
}
63
89
64
90
queue. extend (
65
91
Direction :: iter ( )
66
92
. 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 )
68
94
. map ( |( nx, ny) | ( d + 1 , nx, ny) ) ,
69
95
) ;
70
96
}
71
97
72
- None
73
- }
74
-
75
- fn part1 ( input : & Input ) -> usize {
76
- bfs ( input, input. prefix_len ) . unwrap ( )
98
+ panic ! ( )
77
99
}
78
100
79
101
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
+ }
87
118
}
88
119
}
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 ! ( )
92
134
}
93
135
94
136
aoc:: main!( 2024 , 18 , ex: 1 ) ;
0 commit comments