-
Notifications
You must be signed in to change notification settings - Fork 0
/
nine.rs
119 lines (107 loc) · 4.16 KB
/
nine.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
use libaoc::{Day, DayNumber};
use std::collections::VecDeque;
fn find_and_remove_adjacent(
all_basin_points: &mut VecDeque<(usize, usize)>,
basin_points: &[(usize, usize)],
) -> Option<(usize, usize)> {
for i in 0..all_basin_points.len() {
for &point in basin_points {
let all_point = all_basin_points[i];
if point.0 + 1 == all_point.0 && point.1 == all_point.1
|| point.0 - 1 == all_point.0 && point.1 == all_point.1
|| point.1 + 1 == all_point.1 && point.0 == all_point.0
|| point.1 - 1 == all_point.1 && point.0 == all_point.0
{
return Some(all_basin_points.remove(i).unwrap());
}
}
}
None
}
pub fn nine() -> Day<2021> {
Day::new(
DayNumber::Nine,
|input| {
let lines: Vec<&str> = input.lines().collect();
let height = lines.len();
let width = lines[0].len();
let heightmap: Vec<u8> = lines
.iter()
.map(|&line| line.bytes().map(|byte| byte - b'0').collect::<Vec<u8>>())
.flatten()
.collect();
let mut sum_of_risk_levels = 0_usize;
for i in 0..height {
for j in 0..width {
let current_height = heightmap[i * width + j];
let left = if j == 0 {
u8::MAX
} else {
heightmap[i * width + j - 1]
};
let right = if j == width - 1 {
u8::MAX
} else {
heightmap[i * width + j + 1]
};
let above = if i == 0 {
u8::MAX
} else {
heightmap[(i - 1) * width + j]
};
let below = if i == height - 1 {
u8::MAX
} else {
heightmap[(i + 1) * width + j]
};
if current_height < left
&& current_height < right
&& current_height < above
&& current_height < below
{
// print!("{}", format!("{}", current_height).red());
sum_of_risk_levels += current_height as usize + 1;
} else {
// print!("{}", current_height)
}
}
// println!();
}
Box::new(sum_of_risk_levels)
},
|input| {
let lines: Vec<&str> = input.lines().collect();
let height = lines.len();
let width = lines[0].len();
let heightmap: Vec<u8> = lines
.iter()
.map(|&line| line.bytes().map(|byte| byte - b'0').collect::<Vec<u8>>())
.flatten()
.collect();
let mut basin_points: VecDeque<(usize, usize)> = VecDeque::new();
let mut basins: Vec<Vec<(usize, usize)>> = Vec::new();
for i in 0..height {
for j in 0..width {
if heightmap[i * width + j] != 9 {
basin_points.push_back((i, j));
// print!("{}", format!("{}", heightmap[i * width + j]).red());
} else {
// print!("{}", heightmap[i * width + j]);
}
}
// println!();
}
while !basin_points.is_empty() {
let origin = basin_points.pop_front().unwrap();
let mut basin = vec![origin];
while let Some(adjacent) = find_and_remove_adjacent(&mut basin_points, &basin) {
basin.push(adjacent)
}
basins.push(basin);
}
let mut basin_sizes: Vec<usize> = basins.iter().map(|basin| basin.len()).collect();
basin_sizes.sort_unstable();
Box::new(basin_sizes.iter().rev().take(3).product::<usize>())
},
)
}