11advent_of_code:: solution!( 18 ) ;
22
3- use std:: collections:: VecDeque ;
4-
53use advent_of_code:: maneatingape:: grid:: * ;
6- use advent_of_code:: maneatingape:: hash:: * ;
74use advent_of_code:: maneatingape:: iter:: * ;
85use advent_of_code:: maneatingape:: parse:: * ;
96use advent_of_code:: maneatingape:: point:: * ;
@@ -15,7 +12,11 @@ enum Block {
1512}
1613
1714fn 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}" , ) ;
1920 let ( left, right) = input. split_once ( "\n \n " ) . unwrap_or ( ( input, & default_right) ) ;
2021
2122 let data = left
@@ -29,44 +30,38 @@ fn parse_data(input: &str) -> (Vec<Point>, i32, i32, usize) {
2930 ( data, width, height, first_take as usize )
3031}
3132
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 > {
4734 let start_position = Point :: new ( 0 , 0 ) ;
4835 let end_position = Point :: new ( grid. width - 1 , grid. height - 1 ) ;
4936
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+ } ;
5243
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 ;
5546
56- while let Some ( ( cost , position ) ) = queue. pop_front ( ) {
47+ while let Some ( ( position , cost ) ) = queue. pop_front ( ) {
5748 if position == end_position {
58- return cost;
49+ return Some ( cost) ;
5950 }
6051
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 ;
6560 }
6661 }
6762 }
6863
69- u32 :: MAX
64+ None
7065}
7166
7267fn 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
8681pub fn part_one ( input : & str ) -> Option < u32 > {
8782 let ( data, width, height, first_take) = parse_data ( input) ;
8883
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) ) ? ;
9085
9186 Some ( result)
9287}
@@ -95,15 +90,14 @@ pub fn part_two(input: &str) -> Option<String> {
9590 let ( data, width, height, first_take) = parse_data ( input) ;
9691
9792 let mut a = first_take;
98- let mut b = input . lines ( ) . count ( ) ;
93+ let mut b = data . len ( ) ;
9994 while ( b - a) > 1 {
10095 let c = ( a + b) / 2 ;
10196
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 ( ) {
10698 a = c;
99+ } else {
100+ b = c;
107101 }
108102 }
109103
@@ -118,13 +112,15 @@ mod tests {
118112
119113 #[ test]
120114 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) ;
122117 assert_eq ! ( result, Some ( 22 ) ) ;
123118 }
124119
125120 #[ test]
126121 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) ;
128124 assert_eq ! ( result, Some ( String :: from( "6,1" ) ) ) ;
129125 }
130126}
0 commit comments