Skip to content

Commit 980b0ae

Browse files
committed
12th day
1 parent 9733d8f commit 980b0ae

File tree

1 file changed

+76
-18
lines changed

1 file changed

+76
-18
lines changed

src/bin/12.rs

Lines changed: 76 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
advent_of_code::solution!(12);
22

33
use advent_of_code::maneatingape::grid::*;
4+
use advent_of_code::maneatingape::hash::*;
45
use advent_of_code::maneatingape::point::*;
56

7+
struct Garden {
8+
area: u32,
9+
perimeter: u32,
10+
edges: FastSet<(Point, Point)>,
11+
}
12+
613
fn 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 {
@@ -21,8 +28,11 @@ fn find_data_with_flood(grid: &Grid<u8>) -> Vec<(usize, usize)> {
2128

2229
let plot = grid[start_location];
2330

24-
let mut area = 0;
25-
let mut perimeter = 0;
31+
let mut garden = Garden {
32+
area: 0,
33+
perimeter: 0,
34+
edges: FastSet::new(),
35+
};
2636

2737
let mut queue = vec![start_location];
2838
while let Some(position) = queue.pop() {
@@ -31,52 +41,100 @@ fn find_data_with_flood(grid: &Grid<u8>) -> Vec<(usize, usize)> {
3141
}
3242
visited[position] = true;
3343

34-
area += 1;
35-
perimeter += 4;
44+
garden.area += 1;
45+
garden.perimeter += 4;
3646

37-
for new_position in ORTHOGONAL.map(|o| position + o) {
47+
for direction in ORTHOGONAL {
48+
let new_position = position + direction;
3849
if grid.contains(new_position) && grid[new_position] == plot {
3950
queue.push(new_position);
40-
perimeter -= 1;
51+
garden.perimeter -= 1;
52+
} else {
53+
garden.edges.insert((position, direction));
4154
}
4255
}
4356
}
4457

45-
result.push((area, perimeter));
58+
gardens.push(garden);
59+
}
60+
}
61+
62+
gardens
63+
}
64+
65+
fn find_sides(mut edges: FastSet<(Point, Point)>) -> u32 {
66+
let next_corner_edge = |edges: &FastSet<(Point, Point)>| {
67+
let mut edge = edges.iter().next().copied()?;
68+
loop {
69+
let new_edge = (edge.0 + edge.1.clockwise(), edge.1);
70+
if !edges.contains(&new_edge) {
71+
return Some(edge);
72+
}
73+
74+
edge = new_edge;
75+
}
76+
};
77+
78+
let mut sides = 0;
79+
let mut next_edge = next_corner_edge(&edges);
80+
while let Some(edge @ (p, d)) = next_edge {
81+
edges.remove(&edge);
82+
83+
let left_edge = (p + d.counter_clockwise(), d);
84+
if edges.contains(&left_edge) {
85+
next_edge = Some(left_edge);
86+
continue;
87+
}
88+
89+
let right_edge = (p + d.clockwise(), d);
90+
if edges.contains(&right_edge) {
91+
next_edge = Some(right_edge);
92+
continue;
4693
}
94+
95+
next_edge = next_corner_edge(&edges);
96+
sides += 1;
4797
}
4898

49-
result
99+
sides
50100
}
51101

52102
pub fn part_one(input: &str) -> Option<u32> {
53103
let grid = parse_data(input);
54104

55-
let result = find_data_with_flood(&grid)
105+
let result = find_gardens(&grid)
56106
.into_iter()
57-
.map(|(area, perimeter)| (area * perimeter) as u32)
107+
.map(|garden| garden.area * garden.perimeter)
58108
.sum();
59109

60110
Some(result)
61111
}
62112

63-
pub fn part_two(_input: &str) -> Option<u32> {
64-
None
113+
pub fn part_two(input: &str) -> Option<u32> {
114+
let grid = parse_data(input);
115+
116+
let result = find_gardens(&grid)
117+
.into_iter()
118+
.map(|garden| garden.area * find_sides(garden.edges))
119+
.sum();
120+
121+
Some(result)
65122
}
66123

67124
#[cfg(test)]
68125
mod tests {
69126
use super::*;
70-
71127
#[test]
72128
fn test_part_one() {
73-
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
129+
let input = advent_of_code::template::read_file("examples", DAY);
130+
let result = part_one(&input);
74131
assert_eq!(result, Some(1930));
75132
}
76133

77134
#[test]
78135
fn test_part_two() {
79-
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
80-
assert_eq!(result, None);
136+
let input = advent_of_code::template::read_file("examples", DAY);
137+
let result = part_two(&input);
138+
assert_eq!(result, Some(1206));
81139
}
82140
}

0 commit comments

Comments
 (0)