1
1
use rayon:: prelude:: * ;
2
- use std:: collections:: { HashMap , VecDeque } ;
2
+ use std:: collections:: VecDeque ;
3
3
4
4
const DIRS4 : [ ( i32 , i32 ) ; 4 ] = [ ( 1 , 0 ) , ( 0 , 1 ) , ( 0 , -1 ) , ( -1 , 0 ) ] ;
5
5
@@ -9,31 +9,46 @@ pub struct Pos {
9
9
}
10
10
11
11
pub fn find_cheats (
12
- from_start : & HashMap < ( usize , usize ) , i32 > ,
13
- from_end : & HashMap < ( usize , usize ) , i32 > ,
12
+ from_start : & [ Vec < i32 > ] ,
13
+ from_end : & [ Vec < i32 > ] ,
14
14
e : & Pos ,
15
15
n : i32 ,
16
16
skips_allowed : i32 ,
17
17
) -> i32 {
18
- let end_steps = from_start[ & ( e. i , e. j ) ] ;
18
+ let end_steps = from_start[ e. i ] [ e. j ] ;
19
19
let threshold = if n > 50 { 100 } else { 50 } ;
20
+
20
21
from_start
21
22
. par_iter ( )
22
- . map ( |( & ( i, j) , & _v) | {
23
+ . enumerate ( )
24
+ . map ( |( i, row) | {
23
25
let mut local_result = 0 ;
24
- let steps = from_start[ & ( i, j) ] ;
25
- for di in -20 ..21_i32 {
26
- for dj in ( di. abs ( ) - 20 ) ..( 21 - di. abs ( ) ) {
27
- let ( oi, oj) = ( i as i32 + di, j as i32 + dj) ;
28
- if from_end. contains_key ( & ( oi as usize , oj as usize ) ) {
29
- let d = di. abs ( ) + dj. abs ( ) ;
30
- if d > skips_allowed {
31
- continue ;
32
- }
33
- let total = steps + from_end[ & ( oi as usize , oj as usize ) ] + d;
34
- let saved = end_steps - total;
35
- if saved >= threshold {
36
- local_result += 1 ;
26
+ for ( j, & steps) in row. iter ( ) . enumerate ( ) {
27
+ if steps == -1 {
28
+ continue ;
29
+ }
30
+ for di in -20 ..21_i32 {
31
+ for dj in ( di. abs ( ) - 20 ) ..( 21 - di. abs ( ) ) {
32
+ let oi = i as i32 + di;
33
+ let oj = j as i32 + dj;
34
+ if oi >= 0
35
+ && oi < from_end. len ( ) as i32
36
+ && oj >= 0
37
+ && oj < from_end[ 0 ] . len ( ) as i32
38
+ {
39
+ let oi = oi as usize ;
40
+ let oj = oj as usize ;
41
+ if from_end[ oi] [ oj] != -1 {
42
+ let d = di. abs ( ) + dj. abs ( ) ;
43
+ if d > skips_allowed {
44
+ continue ;
45
+ }
46
+ let total = steps + from_end[ oi] [ oj] + d;
47
+ let saved = end_steps - total;
48
+ if saved >= threshold {
49
+ local_result += 1 ;
50
+ }
51
+ }
37
52
}
38
53
}
39
54
}
@@ -42,33 +57,35 @@ pub fn find_cheats(
42
57
} )
43
58
. sum ( )
44
59
}
45
-
46
60
pub fn bfs ( grid : & [ Vec < char > ] , s : & Pos , e : & Pos ) -> ( i32 , i32 ) {
47
- let mut from_start: HashMap < ( usize , usize ) , i32 > = HashMap :: new ( ) ;
48
- let mut from_end: HashMap < ( usize , usize ) , i32 > = HashMap :: new ( ) ;
49
- let n = grid. len ( ) as i32 ;
50
- let m = grid[ 0 ] . len ( ) as i32 ;
61
+ let n = grid. len ( ) ;
62
+ let m = grid[ 0 ] . len ( ) ;
63
+ let mut from_start = vec ! [ vec![ -1 ; m] ; n] ;
64
+ let mut from_end = vec ! [ vec![ -1 ; m] ; n] ;
65
+
51
66
for iter in 0 ..2 {
52
67
let mut steps = 0 ;
53
68
let mut queue = VecDeque :: new ( ) ;
54
- queue . push_back ( if iter == 0 { ( s. i , s. j ) } else { ( e. i , e. j ) } ) ;
69
+ let start = if iter == 0 { ( s. i , s. j ) } else { ( e. i , e. j ) } ;
55
70
let map = if iter == 0 {
56
71
& mut from_start
57
72
} else {
58
73
& mut from_end
59
74
} ;
75
+
76
+ queue. push_back ( start) ;
60
77
while !queue. is_empty ( ) {
61
78
let qlen = queue. len ( ) ;
62
79
for _ in 0 ..qlen {
63
80
let ( i, j) = queue. pop_front ( ) . unwrap ( ) ;
64
- if map. contains_key ( & ( i , j ) ) {
81
+ if map[ i ] [ j ] != - 1 {
65
82
continue ;
66
83
}
67
- map. insert ( ( i , j ) , steps) ;
84
+ map[ i ] [ j ] = steps;
68
85
for ( di, dj) in DIRS4 . iter ( ) {
69
86
let ( ni, nj) = ( i as i32 + di, j as i32 + dj) ;
70
- if ( 0 ..n) . contains ( & ni)
71
- && ( 0 ..m) . contains ( & nj)
87
+ if ( 0 ..n as i32 ) . contains ( & ni)
88
+ && ( 0 ..m as i32 ) . contains ( & nj)
72
89
&& grid[ ni as usize ] [ nj as usize ] != '#'
73
90
{
74
91
queue. push_back ( ( ni as usize , nj as usize ) ) ;
@@ -78,8 +95,9 @@ pub fn bfs(grid: &[Vec<char>], s: &Pos, e: &Pos) -> (i32, i32) {
78
95
steps += 1 ;
79
96
}
80
97
}
81
- let part_one = find_cheats ( & from_start, & from_end, e, n, 2 ) ;
82
- let part_two = find_cheats ( & from_start, & from_end, e, n, 20 ) ;
98
+
99
+ let part_one = find_cheats ( & from_start, & from_end, e, n as i32 , 2 ) ;
100
+ let part_two = find_cheats ( & from_start, & from_end, e, n as i32 , 20 ) ;
83
101
( part_one, part_two)
84
102
}
85
103
0 commit comments