Skip to content

Commit 466d055

Browse files
committed
Faster simpler approach
1 parent 6eaba1c commit 466d055

File tree

2 files changed

+47
-30
lines changed

2 files changed

+47
-30
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ Performance is reasonable even on older hardware, for example a 2011 MacBook Pro
8383
| 9 | [Disk Fragmenter](https://adventofcode.com/2024/day/9) | [Source](src/year2024/day09.rs) | 106 |
8484
| 10 | [Hoof It](https://adventofcode.com/2024/day/10) | [Source](src/year2024/day10.rs) | 38 |
8585
| 11 | [Plutonian Pebbles](https://adventofcode.com/2024/day/11) | [Source](src/year2024/day11.rs) | 248 |
86-
| 12 | [Garden Groups](https://adventofcode.com/2024/day/12) | [Source](src/year2024/day12.rs) | 1582 |
86+
| 12 | [Garden Groups](https://adventofcode.com/2024/day/12) | [Source](src/year2024/day12.rs) | 761 |
8787

8888
## 2023
8989

src/year2024/day12.rs

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
//! # Garden Groups
22
use crate::util::grid::*;
3-
use crate::util::hash::*;
43
use crate::util::point::*;
54
use std::collections::VecDeque;
65

7-
const CLOCKWISE: [Point; 5] = [UP, RIGHT, DOWN, LEFT, UP];
8-
96
pub fn parse(input: &str) -> Grid<u8> {
107
Grid::parse(input)
118
}
129

1310
pub 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

5855
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();
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

Comments
 (0)