22use crate :: util:: iter:: * ;
33use crate :: util:: parse:: * ;
44
5- type Tile = [ u64 ; 2 ] ;
5+ type Tile = [ u32 ; 2 ] ;
66
77struct Candidate {
8- x : u64 ,
9- y : u64 ,
8+ x : u32 ,
9+ y : u32 ,
1010 interval : Interval ,
1111}
1212
13- /// The set { x in u64 | l <= x <= r }.
13+ /// The set { x in u32 | l <= x <= r }.
1414#[ derive( Clone , Copy ) ]
1515struct Interval {
16- l : u64 ,
17- r : u64 ,
16+ l : u32 ,
17+ r : u32 ,
1818}
1919
2020impl Interval {
21- fn new ( l : u64 , r : u64 ) -> Self {
21+ fn new ( l : u32 , r : u32 ) -> Self {
2222 debug_assert ! ( l <= r) ;
2323
2424 Interval { l, r }
@@ -34,24 +34,20 @@ impl Interval {
3434 Interval :: new ( self . l . max ( other. l ) , self . r . min ( other. r ) )
3535 }
3636
37- fn contains ( self , x : u64 ) -> bool {
37+ fn contains ( self , x : u32 ) -> bool {
3838 self . l <= x && x <= self . r
3939 }
4040}
4141
4242pub fn parse ( input : & str ) -> Vec < Tile > {
43- input. iter_unsigned :: < u64 > ( ) . chunk :: < 2 > ( ) . collect ( )
43+ let mut tiles: Vec < _ > = input. iter_unsigned :: < u32 > ( ) . chunk :: < 2 > ( ) . collect ( ) ;
44+ tiles. sort_unstable_by_key ( |& [ x, y] | ( y, x) ) ;
45+ tiles
4446}
4547
4648pub fn part1 ( tiles : & [ Tile ] ) -> u64 {
47- let mut tiles = tiles. to_vec ( ) ;
48-
49- tiles. sort_by_key ( |& [ x, y] | ( x, y) ) ;
50-
51- let ( top_left_tiles, bottom_left_tiles) =
52- get_potential_left_corner_tiles ( tiles. iter ( ) . copied ( ) ) ;
53-
54- let ( top_right_tiles, bottom_right_tiles) =
49+ let ( top_left_tiles, top_right_tiles) = get_potential_left_corner_tiles ( tiles. iter ( ) . copied ( ) ) ;
50+ let ( bottom_left_tiles, bottom_right_tiles) =
5551 get_potential_left_corner_tiles ( tiles. iter ( ) . copied ( ) . rev ( ) ) ;
5652
5753 find_largest_from_all_corners ( & top_left_tiles, & bottom_right_tiles)
@@ -60,10 +56,10 @@ pub fn part1(tiles: &[Tile]) -> u64 {
6056
6157/// This function filters `sorted_tiles` into two lists, one containing all tiles that could be the top left
6258/// corner of the largest rectangle (assuming the largest rectangle has a top left corner), and the second
63- /// containing all tiles that could be the bottom left corner.
59+ /// containing all tiles that could be the top right corner.
6460///
65- /// It assumes `sorted_tiles` is sorted in ascending "x " values, or, to get the top right and bottom right corners,
66- /// that `sorted_tiles` is sorted in descending "x " order.
61+ /// It assumes `sorted_tiles` is sorted in ascending "y " values, or, to get the top right and bottom right corners,
62+ /// that `sorted_tiles` is sorted in descending "y " order.
6763///
6864/// It works (for the top left corners, for illustration) by only returning tiles (from the set of all tiles, "T") within
6965/// the region:
@@ -82,60 +78,58 @@ pub fn part1(tiles: &[Tile]) -> u64 {
8278/// The `top_tiles` and `bottom_tiles` are the corner points of this region `R`, built up by scanning through tiles
8379/// in either left to right or right to left order.
8480fn get_potential_left_corner_tiles (
85- sorted_tiles : impl Iterator < Item = [ u64 ; 2 ] > ,
86- ) -> ( Vec < [ u64 ; 2 ] > , Vec < [ u64 ; 2 ] > ) {
87- let mut top_tiles = Vec :: new ( ) ;
88- let mut top_tiles_last_y = u64 :: MAX ;
81+ sorted_tiles : impl Iterator < Item = [ u32 ; 2 ] > ,
82+ ) -> ( Vec < [ u32 ; 2 ] > , Vec < [ u32 ; 2 ] > ) {
83+ let mut left_tiles = Vec :: new ( ) ;
84+ let mut left_tiles_last_x = u32 :: MAX ;
8985
90- let mut bottom_tiles = Vec :: new ( ) ;
91- let mut bottom_tiles_last_y = u64 :: MIN ;
86+ let mut right_tiles = Vec :: new ( ) ;
87+ let mut right_tiles_last_x = u32 :: MIN ;
9288
9389 let mut it = sorted_tiles. peekable ( ) ;
9490
95- while let Some ( first_in_column ) = it. next ( ) {
96- let mut last_in_column = first_in_column ;
91+ while let Some ( first_in_row ) = it. next ( ) {
92+ let mut last_in_row = first_in_row ;
9793
98- while let Some ( p) = it. next_if ( |p| p[ 0 ] == first_in_column [ 0 ] ) {
99- last_in_column = p;
94+ while let Some ( p) = it. next_if ( |p| p[ 1 ] == first_in_row [ 1 ] ) {
95+ last_in_row = p;
10096 }
10197
102- let ( x , top_y , bottom_y ) = (
103- first_in_column [ 0 ] ,
104- first_in_column [ 1 ] . min ( last_in_column [ 1 ] ) ,
105- first_in_column [ 1 ] . max ( last_in_column [ 1 ] ) ,
98+ let ( y , left_x , right_x ) = (
99+ first_in_row [ 1 ] ,
100+ first_in_row [ 0 ] . min ( last_in_row [ 0 ] ) ,
101+ first_in_row [ 0 ] . max ( last_in_row [ 0 ] ) ,
106102 ) ;
107103
108- if top_y < top_tiles_last_y {
109- top_tiles . push ( [ x , top_y ] ) ;
110- top_tiles_last_y = top_y ;
104+ if left_x < left_tiles_last_x {
105+ left_tiles . push ( [ left_x , y ] ) ;
106+ left_tiles_last_x = left_x ;
111107 }
112108
113- if bottom_y > bottom_tiles_last_y {
114- bottom_tiles . push ( [ x , bottom_y ] ) ;
115- bottom_tiles_last_y = bottom_y ;
109+ if right_x > right_tiles_last_x {
110+ right_tiles . push ( [ right_x , y ] ) ;
111+ right_tiles_last_x = right_x ;
116112 }
117113 }
118114
119- ( top_tiles , bottom_tiles )
115+ ( left_tiles , right_tiles )
120116}
121117
122118#[ inline]
123- fn find_largest_from_all_corners ( corner : & [ [ u64 ; 2 ] ] , opposite_corner : & [ [ u64 ; 2 ] ] ) -> u64 {
119+ fn find_largest_from_all_corners ( corner : & [ [ u32 ; 2 ] ] , opposite_corner : & [ [ u32 ; 2 ] ] ) -> u64 {
124120 let mut largest = 0_u64 ;
125121
126122 for & p in corner {
127123 for & q in opposite_corner {
128- largest = largest. max ( ( p[ 0 ] . abs_diff ( q[ 0 ] ) + 1 ) * ( p[ 1 ] . abs_diff ( q[ 1 ] ) + 1 ) ) ;
124+ largest =
125+ largest. max ( ( p[ 0 ] . abs_diff ( q[ 0 ] ) + 1 ) as u64 * ( p[ 1 ] . abs_diff ( q[ 1 ] ) + 1 ) as u64 ) ;
129126 }
130127 }
131128
132129 largest
133130}
134131
135132pub fn part2 ( tiles : & [ Tile ] ) -> u64 {
136- let mut tiles = tiles. to_vec ( ) ;
137- tiles. sort_unstable_by_key ( |& [ x, y] | ( y, x) ) ;
138-
139133 // Track the largest area so far during scanning:
140134 let mut largest_area: u64 = 0 ;
141135
@@ -144,13 +138,13 @@ pub fn part2(tiles: &[Tile]) -> u64 {
144138 let mut candidates: Vec < Candidate > = Vec :: with_capacity ( 512 ) ;
145139
146140 // Maintain an ordered list of descending edges, i.e. [begin_interval_0, end_interval_0, begin_interval_1, end_interval_1, ...]:
147- let mut descending_edges: Vec < u64 > = vec ! [ ] ;
141+ let mut descending_edges: Vec < u32 > = vec ! [ ] ;
148142 let mut intervals_from_descending_edges = vec ! [ ] ;
149143
150144 // Invariants on the input data (defined by the puzzle) result in points arriving in pairs on the same y line:
151- let mut it = tiles. into_iter ( ) ;
145+ let mut it = tiles. iter ( ) ;
152146
153- while let ( Some ( [ x0, y] ) , Some ( [ x1, y1] ) ) = ( it. next ( ) , it. next ( ) ) {
147+ while let ( Some ( & [ x0, y] ) , Some ( & [ x1, y1] ) ) = ( it. next ( ) , it. next ( ) ) {
154148 debug_assert_eq ! ( y, y1) ;
155149
156150 // Update the descending edges; since we are scanning from top to bottom, and within each line left to right,
@@ -179,8 +173,9 @@ pub fn part2(tiles: &[Tile]) -> u64 {
179173 for candidate in & candidates {
180174 for x in [ x0, x1] {
181175 if candidate. interval . contains ( x) {
182- largest_area = largest_area
183- . max ( ( candidate. x . abs_diff ( x) + 1 ) * ( candidate. y . abs_diff ( y) + 1 ) ) ;
176+ largest_area = largest_area. max (
177+ ( candidate. x . abs_diff ( x) + 1 ) as u64 * ( candidate. y . abs_diff ( y) + 1 ) as u64 ,
178+ ) ;
184179 }
185180 }
186181 }
@@ -212,7 +207,7 @@ pub fn part2(tiles: &[Tile]) -> u64 {
212207}
213208
214209// Adds `value` if it isn't in `ordered_list`, removes it if it is, maintaining the order.
215- fn toggle_value_membership_in_ordered_list ( ordered_list : & mut Vec < u64 > , value : u64 ) {
210+ fn toggle_value_membership_in_ordered_list ( ordered_list : & mut Vec < u32 > , value : u32 ) {
216211 match ordered_list. binary_search ( & value) {
217212 Ok ( i) => {
218213 ordered_list. remove ( i) ;
@@ -226,7 +221,7 @@ fn toggle_value_membership_in_ordered_list(ordered_list: &mut Vec<u64>, value: u
226221// Changes the list of descending edges, [begin_interval_0, end_interval_0, begin_interval_1, end_interval_1, ...],
227222// into a vector containing the intervals.
228223#[ inline]
229- fn update_intervals_from_descending_edges ( descending_edges : & [ u64 ] , to_update : & mut Vec < Interval > ) {
224+ fn update_intervals_from_descending_edges ( descending_edges : & [ u32 ] , to_update : & mut Vec < Interval > ) {
230225 debug_assert ! ( descending_edges. len( ) . is_multiple_of( 2 ) ) ;
231226
232227 to_update. clear ( ) ;
0 commit comments