1
1
//! # Garden Groups
2
2
use crate :: util:: grid:: * ;
3
- use crate :: util:: hash:: * ;
4
3
use crate :: util:: point:: * ;
5
4
use std:: collections:: VecDeque ;
6
5
7
- const CLOCKWISE : [ Point ; 5 ] = [ UP , RIGHT , DOWN , LEFT , UP ] ;
8
-
9
6
pub fn parse ( input : & str ) -> Grid < u8 > {
10
7
Grid :: parse ( input)
11
8
}
12
9
13
10
pub fn part1 ( grid : & Grid < u8 > ) -> i32 {
11
+ let mut result = 0 ;
14
12
let mut todo = VecDeque :: new ( ) ;
15
13
let mut seen = grid. same_size_with ( false ) ;
16
14
let mut added = grid. same_size_with ( false ) ;
17
- let mut result = 0 ;
18
15
19
16
for y in 0 ..grid. height {
20
17
for x in 0 ..grid. width {
@@ -56,11 +53,10 @@ pub fn part1(grid: &Grid<u8>) -> i32 {
56
53
}
57
54
58
55
pub 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 ( ) ;
63
56
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 ( ) ;
64
60
65
61
for y in 0 ..grid. height {
66
62
for x in 0 ..grid. width {
@@ -70,6 +66,7 @@ pub fn part2(grid: &Grid<u8>) -> u32 {
70
66
}
71
67
72
68
let kind = grid[ point] ;
69
+ let mut added = grid. same_size_with ( false ) ;
73
70
let mut size = 0 ;
74
71
let mut sides = 0 ;
75
72
@@ -78,18 +75,8 @@ pub fn part2(grid: &Grid<u8>) -> u32 {
78
75
79
76
while let Some ( point) = todo. pop_front ( ) {
80
77
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) ;
93
80
94
81
for next in ORTHOGONAL . map ( |o| point + o) {
95
82
if grid. contains ( next) && grid[ next] == kind && !seen[ next] {
@@ -99,19 +86,49 @@ pub fn part2(grid: &Grid<u8>) -> u32 {
99
86
}
100
87
}
101
88
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] ;
105
90
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 ;
110
124
}
125
+ if test ( point + DOWN ) && test ( point + RIGHT ) && !test ( point + DOWN + RIGHT ) {
126
+ dr = 1 ;
127
+ }
128
+
129
+ sides += ul + ur + dl + dr;
111
130
}
112
131
113
- corner. clear ( ) ;
114
- middle. clear ( ) ;
115
132
result += size * sides;
116
133
}
117
134
}
0 commit comments