Skip to content

Commit a1aba67

Browse files
committed
12th day
1 parent 9733d8f commit a1aba67

File tree

1 file changed

+74
-13
lines changed

1 file changed

+74
-13
lines changed

src/bin/12.rs

+74-13
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 {
@@ -24,6 +31,8 @@ fn find_data_with_flood(grid: &Grid<u8>) -> Vec<(usize, usize)> {
2431
let mut area = 0;
2532
let mut perimeter = 0;
2633

34+
let mut edges = FastSet::new();
35+
2736
let mut queue = vec![start_location];
2837
while let Some(position) = queue.pop() {
2938
if visited[position] {
@@ -34,49 +43,101 @@ fn find_data_with_flood(grid: &Grid<u8>) -> Vec<(usize, usize)> {
3443
area += 1;
3544
perimeter += 4;
3645

37-
for new_position in ORTHOGONAL.map(|o| position + o) {
46+
for direction in ORTHOGONAL {
47+
let new_position = position + direction;
3848
if grid.contains(new_position) && grid[new_position] == plot {
3949
queue.push(new_position);
4050
perimeter -= 1;
51+
} else {
52+
edges.insert((position, direction));
4153
}
4254
}
4355
}
4456

45-
result.push((area, perimeter));
57+
gardens.push(Garden {
58+
area,
59+
perimeter,
60+
edges,
61+
});
4662
}
4763
}
4864

49-
result
65+
gardens
66+
}
67+
68+
fn find_sides(mut edges: FastSet<(Point, Point)>) -> u32 {
69+
let next_corner_edge = |edges: &FastSet<(Point, Point)>| {
70+
let mut edge = edges.iter().next().copied()?;
71+
loop {
72+
let new_edge = (edge.0 + edge.1.clockwise(), edge.1);
73+
if !edges.contains(&new_edge) {
74+
return Some(edge);
75+
}
76+
77+
edge = new_edge;
78+
}
79+
};
80+
81+
let mut sides = 0;
82+
let mut next_edge = next_corner_edge(&edges);
83+
while let Some(edge @ (p, d)) = next_edge {
84+
edges.remove(&edge);
85+
86+
let left_edge = (p + d.counter_clockwise(), d);
87+
if edges.contains(&left_edge) {
88+
next_edge = Some(left_edge);
89+
continue;
90+
}
91+
92+
let right_edge = (p + d.clockwise(), d);
93+
if edges.contains(&right_edge) {
94+
next_edge = Some(right_edge);
95+
continue;
96+
}
97+
98+
next_edge = next_corner_edge(&edges);
99+
sides += 1;
100+
}
101+
102+
sides
50103
}
51104

52105
pub fn part_one(input: &str) -> Option<u32> {
53106
let grid = parse_data(input);
54107

55-
let result = find_data_with_flood(&grid)
108+
let result = find_gardens(&grid)
56109
.into_iter()
57-
.map(|(area, perimeter)| (area * perimeter) as u32)
110+
.map(|garden| garden.area * garden.perimeter)
58111
.sum();
59112

60113
Some(result)
61114
}
62115

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

67127
#[cfg(test)]
68128
mod tests {
69129
use super::*;
70-
71130
#[test]
72131
fn test_part_one() {
73-
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
132+
let input = advent_of_code::template::read_file("examples", DAY);
133+
let result = part_one(&input);
74134
assert_eq!(result, Some(1930));
75135
}
76136

77137
#[test]
78138
fn test_part_two() {
79-
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
80-
assert_eq!(result, None);
139+
let input = advent_of_code::template::read_file("examples", DAY);
140+
let result = part_two(&input);
141+
assert_eq!(result, Some(1206));
81142
}
82143
}

0 commit comments

Comments
 (0)