@@ -7,10 +7,9 @@ use nd_vec::{Vec2, vector};
77solution ! ( "Movie Theater" , 9 ) ;
88
99fn part_a ( input : & str ) -> Answer {
10- parse ( input)
11- . iter ( )
12- . combinations ( 2 )
13- . map ( |x| ( x[ 0 ] . x ( ) . abs_diff ( x[ 1 ] . x ( ) ) + 1 ) * ( x[ 0 ] . y ( ) . abs_diff ( x[ 1 ] . y ( ) ) + 1 ) )
10+ ( parse ( input) . iter ( ) )
11+ . tuple_combinations ( )
12+ . map ( |( a, b) | area ( a, b) )
1413 . max ( )
1514 . unwrap ( )
1615 . into ( )
@@ -20,54 +19,21 @@ fn part_b(input: &str) -> Answer {
2019 let red = parse ( input) ;
2120 red. iter ( )
2221 . tuple_combinations ( )
23- . map ( |( a, b) | {
24- (
25- ( a. x ( ) . abs_diff ( b. x ( ) ) + 1 ) * ( a. y ( ) . abs_diff ( b. y ( ) ) + 1 ) ,
26- ( a, b) ,
27- )
28- } )
22+ . map ( |( a, b) | ( area ( a, b) , ( a, b) ) )
2923 . sorted_by_key ( |( area, _) | Reverse ( * area) )
3024 . find ( |( _area, ( a, b) ) | {
31- let min = vector ! ( a. x( ) . min( b. x( ) ) , a. y( ) . min( b. y( ) ) ) ;
32- let max = vector ! ( a. x( ) . max( b. x( ) ) , a. y( ) . max( b. y( ) ) ) ;
33-
34- for ( & α, & β) in red. iter ( ) . chain ( iter:: once ( & red[ 0 ] ) ) . tuple_windows ( ) {
35- let lmin = vector ! ( α. x( ) . min( β. x( ) ) , α. y( ) . min( β. y( ) ) ) ;
36- let lmax = vector ! ( α. x( ) . max( β. x( ) ) , α. y( ) . max( β. y( ) ) ) ;
37-
38- if α. x ( ) == β. x ( ) {
39- let x = β. x ( ) ;
40- if ( ( lmin. y ( ) < min. y ( ) && lmax. y ( ) > min. y ( ) )
41- || ( lmin. y ( ) < max. y ( ) && lmax. y ( ) > max. y ( ) )
42- || ( lmin. y ( ) >= min. y ( ) && lmax. y ( ) <= max. y ( ) ) )
43- && x > min. x ( )
44- && x < max. x ( )
45- {
46- return false ;
47- }
48- } else if α. y ( ) == β. y ( ) {
49- let y = β. y ( ) ;
50- if ( ( lmin. x ( ) < min. x ( ) && lmax. x ( ) > min. x ( ) )
51- || ( lmin. x ( ) < max. x ( ) && lmax. x ( ) > max. x ( ) )
52- || ( lmin. x ( ) >= min. x ( ) && lmax. x ( ) <= max. x ( ) ) )
53- && y > min. y ( )
54- && y < max. y ( )
55- {
56- return false ;
57- }
58- }
59- }
60-
61- true
25+ let bounds = bounds ( a, b) ;
26+ !red. iter ( )
27+ . chain ( iter:: once ( & red[ 0 ] ) )
28+ . tuple_windows ( )
29+ . any ( |line| intersecting_line ( line, bounds) )
6230 } )
6331 . unwrap ( )
6432 . 0
6533 . into ( )
6634}
6735
68- // not: >1565730054
69-
70- fn parse ( input : & str ) -> Vec < Vec2 < i64 > > {
36+ fn parse ( input : & str ) -> Vec < Vec2 < u64 > > {
7137 ( input. lines ( ) )
7238 . map ( |x| {
7339 let ( x, y) = x. split_once ( ',' ) . unwrap ( ) ;
@@ -76,6 +42,37 @@ fn parse(input: &str) -> Vec<Vec2<i64>> {
7642 . collect :: < Vec < _ > > ( )
7743}
7844
45+ fn area ( a : & Vec2 < u64 > , b : & Vec2 < u64 > ) -> u64 {
46+ ( a. x ( ) . abs_diff ( b. x ( ) ) + 1 ) * ( a. y ( ) . abs_diff ( b. y ( ) ) + 1 )
47+ }
48+
49+ fn bounds ( a : & Vec2 < u64 > , b : & Vec2 < u64 > ) -> ( Vec2 < u64 > , Vec2 < u64 > ) {
50+ (
51+ vector ! ( a. x( ) . min( b. x( ) ) , a. y( ) . min( b. y( ) ) ) ,
52+ vector ! ( a. x( ) . max( b. x( ) ) , a. y( ) . max( b. y( ) ) ) ,
53+ )
54+ }
55+
56+ fn intersecting_line (
57+ ( la, lb) : ( & Vec2 < u64 > , & Vec2 < u64 > ) ,
58+ ( min, max) : ( Vec2 < u64 > , Vec2 < u64 > ) ,
59+ ) -> bool {
60+ let ( lmin, lmax) = bounds ( la, lb) ;
61+
62+ la. x ( ) == lb. x ( ) // horizontal line
63+ && ( ( ( lmin. y ( ) < min. y ( ) && lmax. y ( ) > min. y ( ) )
64+ || ( lmin. y ( ) < max. y ( ) && lmax. y ( ) > max. y ( ) )
65+ || ( lmin. y ( ) >= min. y ( ) && lmax. y ( ) <= max. y ( ) ) )
66+ && la. x ( ) > min. x ( )
67+ && la. x ( ) < max. x ( ) )
68+ || la. y ( ) == lb. y ( ) // vertical line
69+ && ( ( ( lmin. x ( ) < min. x ( ) && lmax. x ( ) > min. x ( ) )
70+ || ( lmin. x ( ) < max. x ( ) && lmax. x ( ) > max. x ( ) )
71+ || ( lmin. x ( ) >= min. x ( ) && lmax. x ( ) <= max. x ( ) ) )
72+ && la. y ( ) > min. y ( )
73+ && la. y ( ) < max. y ( ) )
74+ }
75+
7976#[ cfg( test) ]
8077mod test {
8178 use indoc:: indoc;
0 commit comments