11//! # Garden Groups
22use crate :: util:: grid:: * ;
3- use crate :: util:: hash:: * ;
43use crate :: util:: point:: * ;
54use std:: collections:: VecDeque ;
65
7- const CLOCKWISE : [ Point ; 5 ] = [ UP , RIGHT , DOWN , LEFT , UP ] ;
8-
96pub fn parse ( input : & str ) -> Grid < u8 > {
107 Grid :: parse ( input)
118}
129
1310pub fn part1 ( grid : & Grid < u8 > ) -> i32 {
11+ let mut result = 0 ;
1412 let mut todo = VecDeque :: new ( ) ;
1513 let mut seen = grid. same_size_with ( false ) ;
1614 let mut added = grid. same_size_with ( false ) ;
17- let mut result = 0 ;
1815
1916 for y in 0 ..grid. height {
2017 for x in 0 ..grid. width {
@@ -56,11 +53,10 @@ pub fn part1(grid: &Grid<u8>) -> i32 {
5653}
5754
5855pub fn part2 ( grid : & Grid < u8 > ) -> u32 {
59- let mut seen = grid. same_size_with ( false ) ;
60- let mut todo = VecDeque :: new ( ) ;
61- let mut corner = FastMap :: new ( ) ;
62- let mut middle = FastMap :: new ( ) ;
6356 let mut result = 0 ;
57+ let mut todo = VecDeque :: new ( ) ;
58+ let mut seen = grid. same_size_with ( false ) ;
59+ let mut region = Vec :: new ( ) ;
6460
6561 for y in 0 ..grid. height {
6662 for x in 0 ..grid. width {
@@ -70,6 +66,7 @@ pub fn part2(grid: &Grid<u8>) -> u32 {
7066 }
7167
7268 let kind = grid[ point] ;
69+ let mut added = grid. same_size_with ( false ) ;
7370 let mut size = 0 ;
7471 let mut sides = 0 ;
7572
@@ -78,18 +75,8 @@ pub fn part2(grid: &Grid<u8>) -> u32 {
7875
7976 while let Some ( point) = todo. pop_front ( ) {
8077 size += 1 ;
81- let x = 2 * point. x ;
82- let y = 2 * point. y ;
83-
84- * corner. entry ( Point :: new ( x, y) ) . or_insert ( 0 ) += 1 ;
85- * corner. entry ( Point :: new ( x + 2 , y) ) . or_insert ( 0 ) += 1 ;
86- * corner. entry ( Point :: new ( x, y + 2 ) ) . or_insert ( 0 ) += 1 ;
87- * corner. entry ( Point :: new ( x + 2 , y + 2 ) ) . or_insert ( 0 ) += 1 ;
88-
89- * middle. entry ( Point :: new ( x + 1 , y) ) . or_insert ( 0 ) += 1 ;
90- * middle. entry ( Point :: new ( x, y + 1 ) ) . or_insert ( 0 ) += 1 ;
91- * middle. entry ( Point :: new ( x + 2 , y + 1 ) ) . or_insert ( 0 ) += 1 ;
92- * middle. entry ( Point :: new ( x + 1 , y + 2 ) ) . or_insert ( 0 ) += 1 ;
78+ added[ point] = true ;
79+ region. push ( point) ;
9380
9481 for next in ORTHOGONAL . map ( |o| point + o) {
9582 if grid. contains ( next) && grid[ next] == kind && !seen[ next] {
@@ -99,19 +86,49 @@ pub fn part2(grid: &Grid<u8>) -> u32 {
9986 }
10087 }
10188
102- for ( & point, _) in corner. iter ( ) . filter ( |( _, & v) | v < 4 ) {
103- let freq = CLOCKWISE . map ( |c| * middle. get ( & ( point + c) ) . unwrap_or ( & 2 ) ) ;
104- let count = freq. windows ( 2 ) . filter ( |w| w[ 0 ] < 2 && w[ 1 ] < 2 ) . count ( ) ;
89+ let test = |point| added. contains ( point) && added[ point] ;
10590
106- if count == 1 {
107- sides += 1 ;
108- } else if count == 4 {
109- sides += 2 ;
91+ for point in region. drain ( ..) {
92+ let mut ul = 1 ;
93+ let mut ur = 1 ;
94+ let mut dl = 1 ;
95+ let mut dr = 1 ;
96+
97+ // Plots to the side that block off corners
98+ if test ( point + UP ) {
99+ ul = 0 ;
100+ ur = 0 ;
101+ }
102+ if test ( point + DOWN ) {
103+ dl = 0 ;
104+ dr = 0 ;
105+ }
106+ if test ( point + LEFT ) {
107+ ul = 0 ;
108+ dl = 0 ;
109+ }
110+ if test ( point + RIGHT ) {
111+ ur = 0 ;
112+ dr = 0 ;
113+ }
114+
115+ // Concave corners
116+ if test ( point + UP ) && test ( point + LEFT ) && !test ( point + UP + LEFT ) {
117+ ul = 1 ;
118+ }
119+ if test ( point + UP ) && test ( point + RIGHT ) && !test ( point + UP + RIGHT ) {
120+ ur = 1 ;
121+ }
122+ if test ( point + DOWN ) && test ( point + LEFT ) && !test ( point + DOWN + LEFT ) {
123+ dl = 1 ;
110124 }
125+ if test ( point + DOWN ) && test ( point + RIGHT ) && !test ( point + DOWN + RIGHT ) {
126+ dr = 1 ;
127+ }
128+
129+ sides += ul + ur + dl + dr;
111130 }
112131
113- corner. clear ( ) ;
114- middle. clear ( ) ;
115132 result += size * sides;
116133 }
117134 }
0 commit comments