-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday12.rs
136 lines (107 loc) · 3.38 KB
/
day12.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//! [Day 12: Garden Groups](https://adventofcode.com/2024/day/12)
use aoc::{Coord, Direction};
use rustc_hash::{FxHashMap, FxHashSet};
use std::collections::VecDeque;
type Grid = aoc::Grid<u8>;
/// # Panics
#[must_use]
pub fn solve(data: &str) -> (u32, u32) {
let grid = Grid::parse(data);
let mut standard_price = 0;
let mut discount_price = 0;
let mut seen = FxHashSet::default();
for (xy, &plant) in &grid {
let mut area: u32 = 0;
let mut perimeter: u32 = 0;
let mut sides = 0;
let mut queue = VecDeque::new();
let mut side_fences: FxHashMap<Direction, FxHashSet<Coord>> = FxHashMap::default();
queue.push_back(xy);
while let Some(c) = queue.pop_front() {
if seen.contains(&c) {
continue;
}
seen.insert(c);
area += 1;
for (d, neigh) in grid.iter_directions_all(c) {
if let Some(neigh) = neigh {
if grid[neigh] == plant {
// bfs to compute area of current plant
queue.push_back(neigh);
continue;
}
}
// fence: increase perimter
perimeter += 1;
// (part 2)
side_fences.entry(d).or_default().insert(c);
}
}
// println!("{xy:?} {plant} {side_fences:?}");
for vs in side_fences.values() {
let mut seen_sides = FxHashSet::default();
for &p in vs {
if seen_sides.contains(&p) {
continue;
}
sides += 1;
let mut queue_sides = VecDeque::new();
queue_sides.push_back(p);
while let Some(c) = queue_sides.pop_front() {
if seen_sides.contains(&c) {
continue;
}
seen_sides.insert(c);
grid.iter_directions(c)
.filter(|(_, a)| vs.contains(a))
.for_each(|(_, a)| queue_sides.push_back(a));
}
}
}
standard_price += area * perimeter;
discount_price += area * sides;
}
(standard_price, discount_price)
}
pub fn main() {
let args = aoc::parse_args();
args.run(solve);
}
/// Test from answers input
#[cfg(test)]
mod test {
use super::*;
const SAMPLE_1: &str = include_str!("sample_1.txt");
const SAMPLE_3: &str = include_str!("sample_3.txt");
const SAMPLE_4: &str = include_str!("sample_4.txt");
const SAMPLE_6: &str = include_str!("sample_6.txt");
const SAMPLE_7: &str = include_str!("sample_7.txt");
#[test]
fn test01() {
let answers = solve(SAMPLE_1);
assert_eq!(answers.0, 140);
assert_eq!(answers.1, 80);
}
#[test]
fn test02() {
let answers = solve(SAMPLE_3);
assert_eq!(answers.0, 772);
assert_eq!(answers.1, 436);
}
#[test]
fn test03() {
let answers = solve(SAMPLE_4);
assert_eq!(answers.0, 1930);
assert_eq!(answers.1, 1206);
}
#[test]
fn test04() {
let answers = solve(SAMPLE_6);
assert_eq!(answers.1, 236);
}
#[test]
fn test05() {
let answers = solve(SAMPLE_7);
assert_eq!(answers.1, 368);
}
}