11advent_of_code:: solution!( 12 ) ;
22
33use advent_of_code:: maneatingape:: grid:: * ;
4+ use advent_of_code:: maneatingape:: hash:: * ;
45use advent_of_code:: maneatingape:: point:: * ;
56
7+ struct Garden {
8+ area : u32 ,
9+ perimeter : u32 ,
10+ edges : FastSet < ( Point , Point ) > ,
11+ }
12+
613fn parse_data ( input : & str ) -> Grid < u8 > {
714 Grid :: parse ( input)
815}
916
10- fn find_data_with_flood ( grid : & Grid < u8 > ) -> Vec < ( usize , usize ) > {
17+ fn find_gardens ( grid : & Grid < u8 > ) -> Vec < Garden > {
1118 let mut visited = grid. same_size_with ( false ) ;
1219
13- let mut result = vec ! [ ] ;
20+ let mut gardens = vec ! [ ] ;
1421
1522 for y in 0 ..grid. height {
1623 for x in 0 ..grid. width {
@@ -23,6 +30,7 @@ fn find_data_with_flood(grid: &Grid<u8>) -> Vec<(usize, usize)> {
2330
2431 let mut area = 0 ;
2532 let mut perimeter = 0 ;
33+ let mut edges = FastSet :: new ( ) ;
2634
2735 let mut queue = vec ! [ start_location] ;
2836 while let Some ( position) = queue. pop ( ) {
@@ -34,49 +42,101 @@ fn find_data_with_flood(grid: &Grid<u8>) -> Vec<(usize, usize)> {
3442 area += 1 ;
3543 perimeter += 4 ;
3644
37- for new_position in ORTHOGONAL . map ( |o| position + o) {
45+ for direction in ORTHOGONAL {
46+ let new_position = position + direction;
3847 if grid. contains ( new_position) && grid[ new_position] == plot {
3948 queue. push ( new_position) ;
4049 perimeter -= 1 ;
50+ } else {
51+ edges. insert ( ( position, direction) ) ;
4152 }
4253 }
4354 }
4455
45- result. push ( ( area, perimeter) ) ;
56+ gardens. push ( Garden {
57+ area,
58+ perimeter,
59+ edges,
60+ } ) ;
61+ }
62+ }
63+
64+ gardens
65+ }
66+
67+ fn find_sides ( mut edges : FastSet < ( Point , Point ) > ) -> u32 {
68+ let next_corner_edge = |edges : & FastSet < ( Point , Point ) > | {
69+ let mut edge = edges. iter ( ) . next ( ) . copied ( ) ?;
70+ loop {
71+ let new_edge = ( edge. 0 + edge. 1 . clockwise ( ) , edge. 1 ) ;
72+ if !edges. contains ( & new_edge) {
73+ return Some ( edge) ;
74+ }
75+
76+ edge = new_edge;
77+ }
78+ } ;
79+
80+ let mut sides = 0 ;
81+ let mut next_edge = next_corner_edge ( & edges) ;
82+ while let Some ( edge @ ( p, d) ) = next_edge {
83+ edges. remove ( & edge) ;
84+
85+ let left_edge = ( p + d. counter_clockwise ( ) , d) ;
86+ if edges. contains ( & left_edge) {
87+ next_edge = Some ( left_edge) ;
88+ continue ;
89+ }
90+
91+ let right_edge = ( p + d. clockwise ( ) , d) ;
92+ if edges. contains ( & right_edge) {
93+ next_edge = Some ( right_edge) ;
94+ continue ;
4695 }
96+
97+ next_edge = next_corner_edge ( & edges) ;
98+ sides += 1 ;
4799 }
48100
49- result
101+ sides
50102}
51103
52104pub fn part_one ( input : & str ) -> Option < u32 > {
53105 let grid = parse_data ( input) ;
54106
55- let result = find_data_with_flood ( & grid)
107+ let result = find_gardens ( & grid)
56108 . into_iter ( )
57- . map ( |( area , perimeter ) | ( area * perimeter) as u32 )
109+ . map ( |garden| garden . area * garden . perimeter )
58110 . sum ( ) ;
59111
60112 Some ( result)
61113}
62114
63- pub fn part_two ( _input : & str ) -> Option < u32 > {
64- None
115+ pub fn part_two ( input : & str ) -> Option < u32 > {
116+ let grid = parse_data ( input) ;
117+
118+ let result = find_gardens ( & grid)
119+ . into_iter ( )
120+ . map ( |garden| garden. area * find_sides ( garden. edges ) )
121+ . sum ( ) ;
122+
123+ Some ( result)
65124}
66125
67126#[ cfg( test) ]
68127mod tests {
69128 use super :: * ;
70-
71129 #[ test]
72130 fn test_part_one ( ) {
73- let result = part_one ( & advent_of_code:: template:: read_file ( "examples" , DAY ) ) ;
131+ let input = advent_of_code:: template:: read_file ( "examples" , DAY ) ;
132+ let result = part_one ( & input) ;
74133 assert_eq ! ( result, Some ( 1930 ) ) ;
75134 }
76135
77136 #[ test]
78137 fn test_part_two ( ) {
79- let result = part_two ( & advent_of_code:: template:: read_file ( "examples" , DAY ) ) ;
80- assert_eq ! ( result, None ) ;
138+ let input = advent_of_code:: template:: read_file ( "examples" , DAY ) ;
139+ let result = part_two ( & input) ;
140+ assert_eq ! ( result, Some ( 1206 ) ) ;
81141 }
82142}
0 commit comments