-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday-9.rs
102 lines (90 loc) · 2.61 KB
/
day-9.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
use std::str::FromStr;
const INPUT: &str = include_str!("day-9.input");
#[derive(Clone)]
struct Map {
grid: Vec<u8>,
width: usize,
height: usize,
}
impl Map {
fn get(&self, x: isize, y: isize) -> u8 {
if (0..self.width).contains(&(x as usize)) && (0..self.height).contains(&(y as usize)) {
self.grid[y as usize * self.width + x as usize]
} else {
10
}
}
fn for_each(&self, mut f: impl FnMut(isize, isize, u8, u8, u8, u8, u8)) {
for y in 0..self.height {
let y = y as isize;
for x in 0..self.width {
let x = x as isize;
f(
x,
y,
self.get(x, y),
self.get(x, y - 1),
self.get(x + 1, y),
self.get(x, y + 1),
self.get(x - 1, y),
);
}
}
}
fn basin_size(&self, x: isize, y: isize) -> usize {
self.clone().basin_size_r(x, y)
}
fn basin_size_r(&mut self, x: isize, y: isize) -> usize {
if self.get(x, y) >= 9 {
0
} else {
self.grid[y as usize * self.width + x as usize] = 9;
1 + self.basin_size_r(x, y - 1)
+ self.basin_size_r(x + 1, y)
+ self.basin_size_r(x, y + 1)
+ self.basin_size_r(x - 1, y)
}
}
}
impl FromStr for Map {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut width = None;
let grid: Vec<u8> = s
.lines()
.flat_map(|line| {
let line = line.chars().map(|c| c as u8 - b'0').collect::<Vec<_>>();
if let Some(width) = width {
assert_eq!(line.len(), width);
} else {
width = Some(line.len());
}
line
})
.collect();
let width = width.unwrap();
let height = grid.len() / width;
Ok(Self {
grid,
width,
height,
})
}
}
fn main() {
let map: Map = INPUT.parse().unwrap();
let mut risk = 0;
let mut basin_size = Vec::new();
map.for_each(|x, y, c, n, e, s, w| {
if c < n && c < e && c < s && c < w {
risk += c as usize + 1;
basin_size.push(map.basin_size(x, y));
}
});
println!("part 1: {}", risk);
basin_size.sort_unstable();
println!(
"part 2: {}",
basin_size.pop().unwrap() * basin_size.pop().unwrap() * basin_size.pop().unwrap()
);
}