Skip to content

Commit 8b8d9e6

Browse files
committed
12th day
1 parent 9733d8f commit 8b8d9e6

File tree

1 file changed

+73
-13
lines changed

1 file changed

+73
-13
lines changed

Diff for: src/bin/12.rs

+73-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 {
@@ -23,6 +30,7 @@ fn find_data_with_flood(grid: &Grid<u8>) -> Vec<(usize, usize)> {
2330

2431
let mut area = 0;
2532
let mut perimeter = 0;
33+
let mut edges = FastSet::new();
2634

2735
let mut queue = vec![start_location];
2836
while let Some(position) = queue.pop() {
@@ -34,49 +42,101 @@ fn find_data_with_flood(grid: &Grid<u8>) -> Vec<(usize, usize)> {
3442
area += 1;
3543
perimeter += 4;
3644

37-
for new_position in ORTHOGONAL.map(|o| position + o) {
45+
for direction in ORTHOGONAL {
46+
let new_position = position + direction;
3847
if grid.contains(new_position) && grid[new_position] == plot {
3948
queue.push(new_position);
4049
perimeter -= 1;
50+
} else {
51+
edges.insert((position, direction));
4152
}
4253
}
4354
}
4455

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

49-
result
101+
sides
50102
}
51103

52104
pub fn part_one(input: &str) -> Option<u32> {
53105
let grid = parse_data(input);
54106

55-
let result = find_data_with_flood(&grid)
107+
let result = find_gardens(&grid)
56108
.into_iter()
57-
.map(|(area, perimeter)| (area * perimeter) as u32)
109+
.map(|garden| garden.area * garden.perimeter)
58110
.sum();
59111

60112
Some(result)
61113
}
62114

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

67126
#[cfg(test)]
68127
mod tests {
69128
use super::*;
70-
71129
#[test]
72130
fn test_part_one() {
73-
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
131+
let input = advent_of_code::template::read_file("examples", DAY);
132+
let result = part_one(&input);
74133
assert_eq!(result, Some(1930));
75134
}
76135

77136
#[test]
78137
fn test_part_two() {
79-
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
80-
assert_eq!(result, None);
138+
let input = advent_of_code::template::read_file("examples", DAY);
139+
let result = part_two(&input);
140+
assert_eq!(result, Some(1206));
81141
}
82142
}

0 commit comments

Comments
 (0)