1
1
advent_of_code:: solution!( 18 ) ;
2
2
3
- use std:: collections:: VecDeque ;
4
-
5
3
use advent_of_code:: maneatingape:: grid:: * ;
6
- use advent_of_code:: maneatingape:: hash:: * ;
7
4
use advent_of_code:: maneatingape:: iter:: * ;
8
5
use advent_of_code:: maneatingape:: parse:: * ;
9
6
use advent_of_code:: maneatingape:: point:: * ;
@@ -15,7 +12,11 @@ enum Block {
15
12
}
16
13
17
14
fn parse_data ( input : & str ) -> ( Vec < Point > , i32 , i32 , usize ) {
18
- let default_right = format ! ( "{},{},{}" , 71 , 71 , 1024 ) ;
15
+ const DEFAULT_WIDTH : usize = 71 ;
16
+ const DEFAULT_HEIGHT : usize = 71 ;
17
+ const DEFAULT_FIRST_TAKE : usize = 1024 ;
18
+
19
+ let default_right = format ! ( "{DEFAULT_WIDTH},{DEFAULT_HEIGHT},{DEFAULT_FIRST_TAKE}" , ) ;
19
20
let ( left, right) = input. split_once ( "\n \n " ) . unwrap_or ( ( input, & default_right) ) ;
20
21
21
22
let data = left
@@ -29,44 +30,38 @@ fn parse_data(input: &str) -> (Vec<Point>, i32, i32, usize) {
29
30
( data, width, height, first_take as usize )
30
31
}
31
32
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 {
33
+ fn find_shortest_path_cost ( grid : & Grid < Block > ) -> Option < u32 > {
47
34
let start_position = Point :: new ( 0 , 0 ) ;
48
35
let end_position = Point :: new ( grid. width - 1 , grid. height - 1 ) ;
49
36
50
- let mut queue = VecDeque :: new ( ) ;
51
- let mut g_score = FastMap :: new ( ) ;
37
+ let mut queue = std:: collections:: VecDeque :: new ( ) ;
38
+ let mut seen = Grid {
39
+ width : grid. width ,
40
+ height : grid. height ,
41
+ bytes : vec ! [ false ; ( grid. width * grid. height) as usize ] ,
42
+ } ;
52
43
53
- queue. push_front ( ( 0 , start_position ) ) ;
54
- g_score . insert ( start_position, 0 ) ;
44
+ queue. push_front ( ( start_position , 0 ) ) ;
45
+ seen [ start_position] = true ;
55
46
56
- while let Some ( ( cost , position ) ) = queue. pop_front ( ) {
47
+ while let Some ( ( position , cost ) ) = queue. pop_front ( ) {
57
48
if position == end_position {
58
- return cost;
49
+ return Some ( cost) ;
59
50
}
60
51
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) ) ;
52
+ for n_position in ORTHOGONAL . map ( |o| position + o) {
53
+ if !grid. contains ( n_position) || matches ! ( grid[ n_position] , Block :: Corrupted ) {
54
+ continue ;
55
+ }
56
+
57
+ if !seen[ n_position] {
58
+ queue. push_back ( ( n_position, cost + 1 ) ) ;
59
+ seen[ n_position] = true ;
65
60
}
66
61
}
67
62
}
68
63
69
- u32 :: MAX
64
+ None
70
65
}
71
66
72
67
fn generate_grid ( data : & [ Point ] , width : i32 , height : i32 , n : usize ) -> Grid < Block > {
@@ -86,7 +81,7 @@ fn generate_grid(data: &[Point], width: i32, height: i32, n: usize) -> Grid<Bloc
86
81
pub fn part_one ( input : & str ) -> Option < u32 > {
87
82
let ( data, width, height, first_take) = parse_data ( input) ;
88
83
89
- let result = find_shortest_path_cost ( & generate_grid ( & data, width, height, first_take) ) ;
84
+ let result = find_shortest_path_cost ( & generate_grid ( & data, width, height, first_take) ) ? ;
90
85
91
86
Some ( result)
92
87
}
@@ -95,15 +90,14 @@ pub fn part_two(input: &str) -> Option<String> {
95
90
let ( data, width, height, first_take) = parse_data ( input) ;
96
91
97
92
let mut a = first_take;
98
- let mut b = input . lines ( ) . count ( ) ;
93
+ let mut b = data . len ( ) ;
99
94
while ( b - a) > 1 {
100
95
let c = ( a + b) / 2 ;
101
96
102
- let result = find_shortest_path_cost ( & generate_grid ( & data, width, height, c) ) ;
103
- if result == u32:: MAX {
104
- b = c;
105
- } else {
97
+ if find_shortest_path_cost ( & generate_grid ( & data, width, height, c) ) . is_some ( ) {
106
98
a = c;
99
+ } else {
100
+ b = c;
107
101
}
108
102
}
109
103
@@ -118,13 +112,15 @@ mod tests {
118
112
119
113
#[ test]
120
114
fn test_part_one ( ) {
121
- let result = part_one ( & advent_of_code:: template:: read_file ( "examples" , DAY ) ) ;
115
+ let input = advent_of_code:: template:: read_file ( "examples" , DAY ) ;
116
+ let result = part_one ( & input) ;
122
117
assert_eq ! ( result, Some ( 22 ) ) ;
123
118
}
124
119
125
120
#[ test]
126
121
fn test_part_two ( ) {
127
- let result = part_two ( & advent_of_code:: template:: read_file ( "examples" , DAY ) ) ;
122
+ let input = advent_of_code:: template:: read_file ( "examples" , DAY ) ;
123
+ let result = part_two ( & input) ;
128
124
assert_eq ! ( result, Some ( String :: from( "6,1" ) ) ) ;
129
125
}
130
126
}
0 commit comments