11use std:: cmp:: { max, min} ;
2- use std:: collections:: { BTreeSet , HashSet } ;
2+ use std:: collections:: BTreeSet ;
33use std:: iter:: successors;
44
55use aoclp:: positioning:: direction:: four_points:: Direction4 ;
66use aoclp:: positioning:: pt:: { rectangular_area, Pt } ;
77use aoclp:: solvers_impl:: input:: safe_get_input_as_many;
8- use itertools:: Itertools ;
8+ use itertools:: { chain , Either , Itertools } ;
99use aoclp:: positioning:: direction:: Direction ;
1010
1111pub fn part_1 ( ) -> i64 {
@@ -26,7 +26,7 @@ pub fn part_2() -> i64 {
2626 Pt :: new( min( a. x, b. x) , min( a. y, b. y) ) ,
2727 Pt :: new( max( a. x, b. x) , min( a. y, b. y) ) ,
2828 Pt :: new( max( a. x, b. x) , max( a. y, b. y) ) ,
29- Pt :: new( max ( a. x, b. x) , min ( a. y, b. y) ) ,
29+ Pt :: new( min ( a. x, b. x) , max ( a. y, b. y) ) ,
3030 Pt :: new( min( a. x, b. x) , min( a. y, b. y) ) ,
3131 ] ;
3232 let edges: BTreeSet < _ > = corners
@@ -49,46 +49,46 @@ pub fn part_2() -> i64 {
4949 . unwrap ( ) ;
5050 println ! ( "Largest rectangle is ({a}, {b}) area: {area}" ) ;
5151
52- {
53- let red_tiles = input ( ) ;
54- let min_x = red_tiles. iter ( ) . map ( |a| a. x ) . min ( ) . unwrap ( ) - 2 ;
55- let max_x = red_tiles. iter ( ) . map ( |a| a. x ) . max ( ) . unwrap ( ) - 2 ;
56- let min_y = red_tiles. iter ( ) . map ( |a| a. y ) . min ( ) . unwrap ( ) + 2 ;
57- let max_y = red_tiles. iter ( ) . map ( |a| a. y ) . max ( ) . unwrap ( ) + 2 ;
58- let red_tiles: HashSet < _ > = red_tiles. iter ( ) . copied ( ) . collect ( ) ;
59- let corners = vec ! [
60- Pt :: new( min( a. x, b. x) , min( a. y, b. y) ) ,
61- Pt :: new( max( a. x, b. x) , min( a. y, b. y) ) ,
62- Pt :: new( max( a. x, b. x) , max( a. y, b. y) ) ,
63- Pt :: new( max( a. x, b. x) , min( a. y, b. y) ) ,
64- Pt :: new( min( a. x, b. x) , min( a. y, b. y) ) ,
65- ] ;
66- let edges: BTreeSet < _ > = corners
67- . into_iter ( )
68- . tuple_windows ( )
69- . flat_map ( |( a, b) | {
70- let displacement = Pt :: new ( ( b. x - a. x ) . signum ( ) , ( b. y - a. y ) . signum ( ) ) ;
71- successors ( Some ( a) , move |& p| ( p != b) . then_some ( p + displacement) )
72- } )
73- . collect ( ) ;
74-
75- for y in min_x..=max_y {
76- for x in min_y..=max_x {
77- let pt = Pt :: new ( x, y) ;
78- if red_tiles. contains ( & pt) {
79- print ! ( "#" ) ;
80- } else if red_zone. contains ( & pt) {
81- print ! ( "!" ) ;
82- } else if edges. contains ( & pt) {
83- print ! ( "O" ) ;
84- } else {
85- print ! ( "." ) ;
86- }
87- }
88- println ! ( ) ;
89- }
90- println ! ( ) ;
91- }
52+ // {
53+ // let red_tiles = input();
54+ // let min_x = red_tiles.iter().map(|a| a.x).min().unwrap() - 2;
55+ // let max_x = red_tiles.iter().map(|a| a.x).max().unwrap() - 2;
56+ // let min_y = red_tiles.iter().map(|a| a.y).min().unwrap() + 2;
57+ // let max_y = red_tiles.iter().map(|a| a.y).max().unwrap() + 2;
58+ // let red_tiles: HashSet<_> = red_tiles.iter().copied().collect();
59+ // let corners = vec![
60+ // Pt::new(min(a.x, b.x), min(a.y, b.y)),
61+ // Pt::new(max(a.x, b.x), min(a.y, b.y)),
62+ // Pt::new(max(a.x, b.x), max(a.y, b.y)),
63+ // Pt::new(max(a.x, b.x), min(a.y, b.y)),
64+ // Pt::new(min(a.x, b.x), min(a.y, b.y)),
65+ // ];
66+ // let edges: BTreeSet<_> = corners
67+ // .into_iter()
68+ // .tuple_windows()
69+ // .flat_map(|(a, b)| {
70+ // let displacement = Pt::new((b.x - a.x).signum(), (b.y - a.y).signum());
71+ // successors(Some(a), move |&p| (p != b).then_some(p + displacement))
72+ // })
73+ // .collect();
74+ //
75+ // for y in min_x..=max_y {
76+ // for x in min_y..=max_x {
77+ // let pt = Pt::new(x, y);
78+ // if red_tiles.contains(&pt) {
79+ // print!("#");
80+ // } else if red_zone.contains(&pt) {
81+ // print!("!");
82+ // } else if edges.contains(&pt) {
83+ // print!("O");
84+ // } else {
85+ // print!(".");
86+ // }
87+ // }
88+ // println!();
89+ // }
90+ // println!();
91+ // }
9292
9393 area
9494}
@@ -101,26 +101,40 @@ fn build_red_zone(red_tiles: &[Pt]) -> impl Iterator<Item = Pt> + use<'_> {
101101 . next ( )
102102 . unwrap ( ) ;
103103
104+ let get_direction = |a : Pt , b : Pt | match ( ( b. x - a. x ) . signum ( ) , ( b. y - a. y ) . signum ( ) ) {
105+ ( 1 , 0 ) => Direction4 :: Right ,
106+ ( 0 , 1 ) => Direction4 :: Down ,
107+ ( -1 , 0 ) => Direction4 :: Left ,
108+ ( 0 , -1 ) => Direction4 :: Up ,
109+ _ => unreachable ! ( ) ,
110+ } ;
111+
104112 red_tiles
105113 . iter ( )
106114 . copied ( )
107115 . cycle ( )
108116 . skip_while ( move |& p| p != starting_point)
109- . enumerate ( )
110- . take_while ( move |& ( i, p) | i == 0 || p != starting_point)
111- . map ( |( _, p) | p)
117+ . take ( red_tiles. len ( ) + 1 )
112118 . tuple_windows ( )
113- . flat_map ( |( a, b) | {
114- let direction = match ( ( b. x - a. x ) . signum ( ) , ( b. y - a. y ) . signum ( ) ) {
115- ( 1 , 0 ) => Direction4 :: Right ,
116- ( 0 , 1 ) => Direction4 :: Down ,
117- ( -1 , 0 ) => Direction4 :: Left ,
118- ( 0 , -1 ) => Direction4 :: Up ,
119- _ => unreachable ! ( ) ,
120- } ;
121- successors ( Some ( a) , move |& p| ( p != b) . then_some ( p + direction) )
119+ . flat_map ( move |( a, b, c) | {
120+ let direction = get_direction ( a, b) ;
121+ let turning_left = get_direction ( b, c) == direction. turn_left ( ) ;
122+
123+ let red_zone_path = successors ( Some ( a) , move |& p| ( p != b) . then_some ( p + direction) )
122124 . skip ( 1 )
123- . map ( move |p| p + ( direction. turn_left ( ) ) )
125+ . map ( move |p| p + ( direction. turn_left ( ) ) ) ;
126+ if turning_left {
127+ Either :: Left ( red_zone_path)
128+ } else {
129+ Either :: Right ( chain (
130+ red_zone_path,
131+ vec ! [
132+ b + direction. turn_left( ) ,
133+ b + direction + direction. turn_left( ) ,
134+ b + direction,
135+ ] ,
136+ ) )
137+ }
124138 } )
125139}
126140
0 commit comments