11use std:: cmp:: { max, min} ;
2- use std:: collections:: HashMap ;
2+ use std:: collections:: HashSet ;
33use std:: iter:: { once, 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;
88use itertools:: Itertools ;
9+ use aoclp:: positioning:: turtle:: Turtle ;
910
1011pub fn part_1 ( ) -> i64 {
1112 input ( )
@@ -18,41 +19,14 @@ pub fn part_1() -> i64 {
1819
1920pub fn part_2 ( ) -> i64 {
2021 let red_tiles = input ( ) ;
21- let path = build_path ( & red_tiles) ;
2222
23- let safe_line = red_tiles. iter ( ) . map ( |p| p. y ) . min ( ) . unwrap ( ) - 1 ;
24- let mut pt_safety = HashMap :: new ( ) ;
25- let mut safe_pt = |p : Pt | {
26- if let Some ( & safe) = pt_safety. get ( & p) {
27- return safe;
28- }
29-
30- let safe = successors ( Some ( p) , |& p| ( p. y > safe_line) . then_some ( p + Direction4 :: Up ) )
31- . filter ( |p| path. get ( p) . is_some_and ( |& step| step == PathStep :: LeftRight ) )
32- . count ( )
33- % 2
34- != 0 ;
35- pt_safety. insert ( p, safe) ;
36- safe
37- } ;
38- let mut safe_line = |a : Pt , b : Pt | -> bool {
39- let displacement = Pt :: new ( ( b. x - a. x ) . signum ( ) , ( b. y - a. y ) . signum ( ) ) ;
40- successors ( Some ( a) , |& p| ( p != b) . then_some ( p + displacement) )
41- . chain ( Some ( b) )
42- . all ( & mut safe_pt)
23+ let red_zone = build_red_zone ( & red_tiles) ;
24+ let rectangle_points = |a : Pt , b : Pt | {
25+ let ( left, right, top, bottom) = ( min ( a. x , b. x ) , max ( a. x , b. x ) , min ( a. y , b. y ) , max ( a. y , b. y ) ) ;
26+ ( left..=right) . flat_map ( move |x| ( top..=bottom) . map ( move |y| Pt :: new ( x, y) ) )
4327 } ;
44- let mut safe_rectangle = |a : Pt , b : Pt | {
45- let corners = [
46- Pt :: new ( min ( a. x , b. x ) , min ( a. y , b. y ) ) ,
47- Pt :: new ( min ( a. x , b. x ) , max ( a. y , b. y ) ) ,
48- Pt :: new ( max ( a. x , b. x ) , max ( a. y , b. y ) ) ,
49- Pt :: new ( max ( a. x , b. x ) , min ( a. y , b. y ) ) ,
50- Pt :: new ( min ( a. x , b. x ) , min ( a. y , b. y ) ) ,
51- ] ;
52- corners
53- . iter ( )
54- . tuple_windows ( )
55- . all ( |( & a, & b) | safe_line ( a, b) )
28+ let safe_rectangle = |a, b| {
29+ rectangle_points ( a, b) . all ( |p| !red_zone. contains ( & p) )
5630 } ;
5731
5832 red_tiles
@@ -66,38 +40,54 @@ pub fn part_2() -> i64 {
6640 . unwrap ( )
6741}
6842
69- #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
70- enum PathStep {
71- Corner ,
72- LeftRight ,
73- TopDown ,
74- }
75-
76- impl PathStep {
77- fn for_pair ( a : Pt , b : Pt ) -> Self {
78- if ( a. x - b. x ) . abs ( ) . signum ( ) != 0 {
79- Self :: LeftRight
80- } else {
81- Self :: TopDown
82- }
83- }
84- }
85-
86- fn build_path ( red_tiles : & [ Pt ] ) -> HashMap < Pt , PathStep > {
87- red_tiles
43+ fn build_red_zone ( red_tiles : & [ Pt ] ) -> HashSet < Pt > {
44+ let path_tiles: HashSet < _ > = red_tiles
8845 . iter ( )
8946 . copied ( )
9047 . chain ( once ( red_tiles[ 0 ] ) )
9148 . tuple_windows ( )
9249 . flat_map ( |( a, b) | {
93- let step = PathStep :: for_pair ( a, b) ;
9450 let displacement = Pt :: new ( ( b. x - a. x ) . signum ( ) , ( b. y - a. y ) . signum ( ) ) ;
95- successors ( Some ( ( a, PathStep :: Corner ) ) , move |& ( p, _) | {
96- ( p != b) . then_some ( ( p + displacement, step) )
97- } )
98- . chain ( once ( ( b, PathStep :: Corner ) ) )
51+ successors ( Some ( a) , move |& p| ( p != b) . then_some ( p + displacement) )
52+ . chain ( once ( b) )
9953 } )
100- . collect ( )
54+ . collect ( ) ;
55+ let path_tiles = & path_tiles;
56+
57+ println ! ( "Path tiles count: {}" , path_tiles. len( ) ) ;
58+
59+ let starting_point = red_tiles
60+ . iter ( )
61+ . sorted_by ( |a, b| a. x . cmp ( & b. x ) . then ( a. y . cmp ( & b. y ) ) )
62+ . copied ( )
63+ . next ( )
64+ . unwrap ( ) ;
65+
66+ println ! ( "Starting point: {starting_point}" ) ;
67+
68+ let starting_turtle = Turtle :: new ( starting_point, Direction4 :: Right ) ;
69+ let turtle_path = successors ( Some ( ( starting_turtle, 0usize ) ) , move |& ( t, i) | {
70+ if t == starting_turtle && i != 0 {
71+ return None ;
72+ }
73+ Some ( [ t, t. turn_left ( ) , t. turn_right ( ) ]
74+ . iter ( )
75+ . map ( |next| ( next. advance ( ) , i + 1 ) )
76+ . find ( |( next, _) | path_tiles. contains ( & next. position ) )
77+ . unwrap ( ) )
78+ } ) ;
79+
80+ let red_zone: HashSet < _ > = turtle_path
81+ . map ( |( turtle, _) | turtle. turn_left ( ) . advance ( ) )
82+ . filter ( |turtle| !path_tiles. contains ( & turtle. position ) )
83+ . map ( |turtle| turtle. position )
84+ . collect ( ) ;
85+
86+ if !red_zone. is_empty ( ) {
87+ println ! ( "Red zone tiles count: {}" , red_zone. len( ) ) ;
88+ }
89+
90+ red_zone
10191}
10292
10393fn input ( ) -> Vec < Pt > {
0 commit comments