1+ use std:: collections:: HashSet ;
12use std:: fmt;
23use std:: iter:: once;
34
45use aoclp:: positioning:: direction:: four_points:: Direction4 ;
56use aoclp:: positioning:: direction:: { Direction , MovementDirection } ;
67use aoclp:: positioning:: pt:: { min_max, rectangle_corners, rectangular_area, Pt } ;
7- use aoclp:: solvers_impl:: input:: safe_get_input_as_many;
8+ use aoclp:: solvers_impl:: input:: { safe_get_input_as_many, Input } ;
89use itertools:: Itertools ;
910use strum:: IntoEnumIterator ;
1011
@@ -21,21 +22,85 @@ pub fn part_2() -> i64 {
2122 let red_tiles = input ( ) ;
2223 let walls = walls ( & red_tiles) . collect_vec ( ) ;
2324
24- red_tiles
25- . into_iter ( )
25+ let valid_rectangle = |a : Pt , b : Pt | {
26+ let corners = rectangle_corners ( a, b) ;
27+ corners
28+ . into_iter ( )
29+ . chain ( once ( corners[ 0 ] ) )
30+ . tuple_windows ( )
31+ . map ( |( a, b) | GridLine :: from_endpoints ( a, b) )
32+ . all ( |line| !walls. iter ( ) . any ( |w| w. intersects ( line) ) )
33+ } ;
34+
35+ let area = red_tiles
36+ . iter ( )
37+ . copied ( )
2638 . array_combinations ( )
27- . filter ( |[ a, b] | {
28- let corners = rectangle_corners ( * a, * b) ;
29- corners
30- . into_iter ( )
31- . chain ( once ( corners[ 0 ] ) )
32- . tuple_windows ( )
33- . map ( |( a, b) | GridLine :: from_endpoints ( a, b) )
34- . all ( |line| !walls. iter ( ) . any ( |w| w. intersects ( line) ) )
35- } )
39+ . filter ( |[ a, b] | valid_rectangle ( * a, * b) )
3640 . map ( |[ a, b] | rectangular_area ( a, b) )
3741 . max ( )
38- . unwrap ( )
42+ . unwrap ( ) ;
43+
44+ let matching_rects = red_tiles
45+ . iter ( )
46+ . copied ( )
47+ . array_combinations ( )
48+ . map ( |[ a, b] | ( a, b, rectangular_area ( a, b) ) )
49+ . filter ( |( _, _, ar) | * ar == area)
50+ . filter ( |( a, b, _) | valid_rectangle ( * a, * b) )
51+ . collect_vec ( ) ;
52+
53+ println ! ( "The largest rectangle has an area of {area}. Matching rectangles:" ) ;
54+ for ( a, b, _) in matching_rects {
55+ println ! ( " {a} - {b}" ) ;
56+ }
57+
58+ // let line_pts = |line: GridLine| {
59+ // match line {
60+ // GridLine::Horizontal { y, left_x, right_x } => {
61+ // (left_x..=right_x).map(|x| Pt::new(x, y)).collect_vec()
62+ // },
63+ // GridLine::Vertical { x, top_y, bottom_y } => {
64+ // (top_y..=bottom_y).map(|y| Pt::new(x, y)).collect_vec()
65+ // },
66+ // GridLine::Point(p) => vec![p],
67+ // }
68+ // };
69+ //
70+ // let red_tiles_s: HashSet<_> = red_tiles.iter().copied().collect();
71+ // let path_s: HashSet<_> = red_tiles
72+ // .iter()
73+ // .copied()
74+ // .chain(once(red_tiles[0]))
75+ // .tuple_windows()
76+ // .flat_map(|(a, b)| line_pts(GridLine::from_endpoints(a, b)))
77+ // .collect();
78+ // let walls_s: HashSet<_> = walls
79+ // .iter()
80+ // .flat_map(|w| line_pts(*w))
81+ // .collect();
82+ //
83+ // let max_x = red_tiles.iter().map(|p| p.x).max().unwrap() + 3;
84+ // let max_y = red_tiles.iter().map(|p| p.y).max().unwrap() + 3;
85+ //
86+ // for y in 0..=max_y {
87+ // for x in 0..=max_x {
88+ // let p = Pt::new(x, y);
89+ // if red_tiles_s.contains(&p) {
90+ // print!("#");
91+ // } else if walls_s.contains(&p) {
92+ // print!("!");
93+ // } else if path_s.contains(&p) {
94+ // print!("X");
95+ // } else {
96+ // print!(".");
97+ // }
98+ // }
99+ // println!();
100+ // }
101+ // println!();
102+
103+ area
39104}
40105
41106#[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
@@ -142,18 +207,23 @@ fn walls(red_tiles: &[Pt]) -> impl Iterator<Item = GridLine> + use<'_> {
142207 . skip_while ( move |& p| p != starting_point)
143208 . take ( red_tiles. len ( ) + 2 )
144209 . tuple_windows ( )
145- . map ( move |( a, b, c) | {
210+ . scan ( true , move |turned_right , ( a, b, c) | {
146211 let direction = get_direction ( a, b) ;
147212 let turning_right = get_direction ( b, c) == direction. turn_right ( ) ;
148213
149214 let mut line = GridLine :: from_endpoints (
150215 a + direction + direction. turn_left ( ) ,
151216 b + direction. turn_around ( ) + direction. turn_left ( ) ,
152217 ) ;
218+ if * turned_right {
219+ line = line. extend ( direction. turn_around ( ) , 1 ) ;
220+ }
153221 if turning_right {
154222 line = line. extend ( direction, 2 ) ;
155223 }
156- line
224+
225+ * turned_right = turning_right;
226+ Some ( line)
157227 } )
158228}
159229
@@ -170,3 +240,7 @@ const EXAMPLE: &str = "\
170240fn input ( ) -> Vec < Pt > {
171241 safe_get_input_as_many ( 2025 , 9 )
172242}
243+
244+ fn example ( ) -> Vec < Pt > {
245+ Input :: for_example ( EXAMPLE ) . safe_into_many ( )
246+ }
0 commit comments