1- use crate :: util:: grid:: * ;
21use crate :: util:: hash:: * ;
3- use crate :: util:: iter:: * ;
42use crate :: util:: parse:: * ;
5- use crate :: util:: point:: * ;
6- use std:: collections:: VecDeque ;
7-
8- const OUTSIDE : i64 = 0 ;
9- const INSIDE : i64 = 1 ;
10- const UNKNOWN : i64 = 2 ;
113
124type Tile = [ u64 ; 2 ] ;
135
@@ -20,9 +12,7 @@ pub fn part1(tiles: &[Tile]) -> u64 {
2012
2113 for ( i, & [ x1, y1] ) in tiles. iter ( ) . enumerate ( ) {
2214 for & [ x2, y2] in tiles. iter ( ) . skip ( i + 1 ) {
23- let dx = x1. abs_diff ( x2) + 1 ;
24- let dy = y1. abs_diff ( y2) + 1 ;
25- area = area. max ( dx * dy) ;
15+ area = area. max ( rect_area ( x1, y1, x2, y2) ) ;
2616 }
2717 }
2818
@@ -31,74 +21,59 @@ pub fn part1(tiles: &[Tile]) -> u64 {
3121
3222pub fn part2 ( tiles : & [ Tile ] ) -> u64 {
3323 let size = tiles. len ( ) ;
34- let shrink_x = shrink ( tiles, 0 ) ;
35- let shrink_y = shrink ( tiles, 1 ) ;
36- let shrunk: Vec < _ > = tiles. iter ( ) . map ( |& [ x, y] | ( shrink_x[ & x] , shrink_y[ & y] ) ) . collect ( ) ;
3724
25+ // Find top K longest edges and collect candidate vertices
26+ let mut edge_lengths: Vec < ( u64 , usize ) > = ( 0 ..size)
27+ . map ( |i| {
28+ let j = ( i + 1 ) % size;
29+ let dx = tiles[ i] [ 0 ] . abs_diff ( tiles[ j] [ 0 ] ) ;
30+ let dy = tiles[ i] [ 1 ] . abs_diff ( tiles[ j] [ 1 ] ) ;
31+ ( dx. max ( dy) , i)
32+ } )
33+ . collect ( ) ;
34+ edge_lengths. sort_unstable_by ( |a, b| b. 0 . cmp ( & a. 0 ) ) ;
35+
36+ let mut candidates: Vec < usize > = Vec :: with_capacity ( 8 ) ;
37+ for & ( _, i) in edge_lengths. iter ( ) . take ( 4 ) {
38+ candidates. push ( i) ;
39+ candidates. push ( ( i + 1 ) % size) ;
40+ }
41+ candidates. sort_unstable ( ) ;
42+ candidates. dedup ( ) ;
43+
44+ // Build edge AABBs for collision detection
45+ let edges: Vec < _ > = ( 0 ..size)
46+ . map ( |i| {
47+ let j = ( i + 1 ) % size;
48+ let [ x1, y1] = tiles[ i] ;
49+ let [ x2, y2] = tiles[ j] ;
50+ ( x1. min ( x2) , x1. max ( x2) , y1. min ( y2) , y1. max ( y2) )
51+ } )
52+ . collect ( ) ;
53+
54+ // Check candidates paired with all vertices
3855 let mut area = 0 ;
39- let mut todo = VecDeque :: from ( [ ORIGIN ] ) ;
40- let mut grid = Grid :: new ( shrink_x. len ( ) as i32 , shrink_y. len ( ) as i32 , UNKNOWN ) ;
4156
42- for i in 0 ..size {
43- let ( x1 , y1 , x2 , y2 ) = minmax ( shrunk [ i ] , shrunk [ ( i + 1 ) % size ] ) ;
57+ for & c in & candidates {
58+ let [ cx , cy ] = tiles [ c ] ;
4459
45- for x in x1..x2 + 1 {
46- for y in y1..y2 + 1 {
47- grid [ Point :: new ( x , y ) ] = INSIDE ;
60+ for ( i , & [ x , y ] ) in tiles . iter ( ) . enumerate ( ) {
61+ if i == c {
62+ continue ;
4863 }
49- }
50- }
5164
52- while let Some ( point) = todo. pop_front ( ) {
53- for next in ORTHOGONAL . map ( |o| point + o) {
54- if grid. contains ( next) && grid[ next] == UNKNOWN {
55- grid[ next] = OUTSIDE ;
56- todo. push_back ( next) ;
57- }
58- }
59- }
65+ let ( min_x, max_x) = if cx < x { ( cx, x) } else { ( x, cx) } ;
66+ let ( min_y, max_y) = if cy < y { ( cy, y) } else { ( y, cy) } ;
6067
61- for y in 1 ..grid. height {
62- for x in 1 ..grid. width {
63- let point = Point :: new ( x, y) ;
64- let value = i64:: from ( grid[ point] != OUTSIDE ) ;
65- grid[ point] = value + grid[ point + UP ] + grid[ point + LEFT ] - grid[ point + UP + LEFT ] ;
66- }
67- }
68+ let valid = !edges. iter ( ) . any ( |& ( ex1, ex2, ey1, ey2) | {
69+ min_x < ex2 && max_x > ex1 && min_y < ey2 && max_y > ey1
70+ } ) ;
6871
69- for i in 0 ..size {
70- for j in i + 1 ..size {
71- let ( x1, y1, x2, y2) = minmax ( shrunk[ i] , shrunk[ j] ) ;
72-
73- let expected = ( x2 - x1 + 1 ) as i64 * ( y2 - y1 + 1 ) as i64 ;
74- let actual = grid[ Point :: new ( x2, y2) ]
75- - grid[ Point :: new ( x1 - 1 , y2) ]
76- - grid[ Point :: new ( x2, y1 - 1 ) ]
77- + grid[ Point :: new ( x1 - 1 , y1 - 1 ) ] ;
78-
79- if expected == actual {
80- let [ x1, y1] = tiles[ i] ;
81- let [ x2, y2] = tiles[ j] ;
82- let dx = x1. abs_diff ( x2) + 1 ;
83- let dy = y1. abs_diff ( y2) + 1 ;
84- area = area. max ( dx * dy) ;
72+ if valid {
73+ area = area. max ( rect_area ( cx, cy, x, y) ) ;
8574 }
8675 }
8776 }
8877
8978 area
9079}
91-
92- fn shrink ( tiles : & [ Tile ] , index : usize ) -> FastMap < u64 , i32 > {
93- let mut axis: Vec < _ > = tiles. iter ( ) . map ( |tile| tile[ index] ) . collect ( ) ;
94- axis. push ( u64:: MIN ) ;
95- axis. push ( u64:: MAX ) ;
96- axis. sort_unstable ( ) ;
97- axis. dedup ( ) ;
98- axis. iter ( ) . enumerate ( ) . map ( |( i, & n) | ( n, i as i32 ) ) . collect ( )
99- }
100-
101- #[ inline]
102- fn minmax ( ( x1, y1) : ( i32 , i32 ) , ( x2, y2) : ( i32 , i32 ) ) -> ( i32 , i32 , i32 , i32 ) {
103- ( x1. min ( x2) , y1. min ( y2) , x1. max ( x2) , y1. max ( y2) )
104- }
0 commit comments