tangled
alpha
login
or
join now
nove.dev
/
aoc-2025
1
fork
atom
:)
1
fork
atom
overview
issues
pulls
pipelines
factor out some of the generic spatial code
nove.dev
3 months ago
a5541f19
34f84838
+77
-84
3 changed files
expand all
collapse all
unified
split
src
day4.rs
lib.rs
spatial.rs
+4
-84
src/day4.rs
···
1
1
-
use itertools::Itertools;
1
1
+
use crate::spatial::*;
2
2
3
3
pub fn day4_part1(input: &str) -> String {
4
4
let roll_locations = parse(input);
5
5
-
removable_rolls(&roll_locations).len().to_string()
5
5
+
removable_rolls(&roll_locations).count().to_string()
6
6
}
7
7
//fixed point algorithm go brrr
8
8
pub fn day4_part2(input: &str) -> String {
···
19
19
rolls_removed.to_string()
20
20
}
21
21
22
22
-
23
23
-
fn removable_rolls(roll_locations: &[Vec<bool>]) -> Vec<Point> {
22
22
+
fn removable_rolls(roll_locations: &[Vec<bool>]) -> impl Iterator<Item = Point> {
24
23
all_coords(roll_locations[0].len(), roll_locations.len())
25
24
.filter(|coords| roll_locations[coords.row][coords.col])
26
25
.filter(|&coords| {
···
30
29
.filter(|&&neighbour| neighbour)
31
30
.count()
32
31
< 4
33
33
-
}).collect()
32
32
+
})
34
33
}
35
34
36
35
fn parse(input: &str) -> Vec<Vec<bool>> {
···
39
38
.map(|line| line.chars().map(|c| c == '@').collect())
40
39
.collect()
41
40
}
42
42
-
43
43
-
fn unparse(grid: &[Vec<bool>]) -> String {
44
44
-
grid.iter()
45
45
-
.map(|row| {
46
46
-
row.iter()
47
47
-
.map(|&is_roll| if is_roll { '@' } else { '.' })
48
48
-
.collect::<String>()
49
49
-
})
50
50
-
.join("\n")
51
51
-
}
52
52
-
53
53
-
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
54
54
-
struct Point {
55
55
-
row: usize,
56
56
-
col: usize,
57
57
-
}
58
58
-
59
59
-
fn all_coords(width: usize, height: usize) -> impl Iterator<Item = Point> {
60
60
-
(0..height)
61
61
-
.cartesian_product(0..width)
62
62
-
.map(|(row, col)| Point { row, col })
63
63
-
}
64
64
-
65
65
-
/// North, East, South, West, Northeast, Southeast, Southwest, Northwest
66
66
-
fn adjacent_including_diagonals<T: Copy + std::fmt::Debug>(
67
67
-
grid: &[Vec<T>],
68
68
-
coords: Point,
69
69
-
) -> [Option<T>; 8] {
70
70
-
[
71
71
-
adjacent_cardinal(grid, coords),
72
72
-
adjacent_ordinal(grid, coords),
73
73
-
]
74
74
-
.concat()
75
75
-
.try_into()
76
76
-
.unwrap()
77
77
-
}
78
78
-
79
79
-
///Never Eat Shredded Wheat
80
80
-
fn adjacent_cardinal<T: Copy>(grid: &[Vec<T>], coords: Point) -> [Option<T>; 4] {
81
81
-
let mut retval = [const { None }; 4];
82
82
-
let (row, col) = (coords.row, coords.col);
83
83
-
84
84
-
if row > 0 {
85
85
-
retval[0] = Some(grid[row - 1][col]) //N
86
86
-
}
87
87
-
if col < grid[0].len() - 1 {
88
88
-
retval[1] = Some(grid[row][col + 1]) //E
89
89
-
}
90
90
-
if row < grid.len() - 1 {
91
91
-
retval[2] = Some(grid[row + 1][col]) //S
92
92
-
}
93
93
-
if col > 0 {
94
94
-
retval[3] = Some(grid[row][col - 1]) //N
95
95
-
}
96
96
-
97
97
-
retval
98
98
-
}
99
99
-
100
100
-
/// Never Eat Shredded Wheat, rotated 45 degrees clockwise
101
101
-
/// AKA northeast, southeast, southwest, northwest
102
102
-
fn adjacent_ordinal<T: Copy>(grid: &[Vec<T>], coords: Point) -> [Option<T>; 4] {
103
103
-
let mut retval = [const { None }; 4];
104
104
-
let (row, col) = (coords.row, coords.col);
105
105
-
106
106
-
if row > 0 && col < grid[0].len() - 1 {
107
107
-
retval[0] = Some(grid[row - 1][col + 1]) //NE
108
108
-
}
109
109
-
if row < grid.len() - 1 && col < grid[0].len() - 1 {
110
110
-
retval[1] = Some(grid[row + 1][col + 1]) //SE
111
111
-
}
112
112
-
if row < grid.len() - 1 && col > 0 {
113
113
-
retval[2] = Some(grid[row + 1][col - 1]) //SW
114
114
-
}
115
115
-
if row > 0 && col > 0 {
116
116
-
retval[3] = Some(grid[row - 1][col - 1]) //NW
117
117
-
}
118
118
-
119
119
-
retval
120
120
-
}
+1
src/lib.rs
···
117
117
118
118
pub mod day3;
119
119
pub mod day4;
120
120
+
mod spatial;
120
121
121
122
#[cfg(test)]
122
123
mod tests {
+72
src/spatial.rs
···
1
1
+
use itertools::Itertools;
2
2
+
3
3
+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4
4
+
pub struct Point {
5
5
+
pub row: usize,
6
6
+
pub col: usize,
7
7
+
}
8
8
+
9
9
+
pub fn all_coords(width: usize, height: usize) -> impl Iterator<Item = Point> {
10
10
+
(0..height)
11
11
+
.cartesian_product(0..width)
12
12
+
.map(|(row, col)| Point { row, col })
13
13
+
}
14
14
+
15
15
+
/// North, East, South, West, Northeast, Southeast, Southwest, Northwest
16
16
+
/// Depends on `coords` being within bounds
17
17
+
pub fn adjacent_including_diagonals<T: Copy + std::fmt::Debug>(
18
18
+
grid: &[Vec<T>],
19
19
+
coords: Point,
20
20
+
) -> [Option<T>; 8] {
21
21
+
[
22
22
+
adjacent_cardinal(grid, coords),
23
23
+
adjacent_ordinal(grid, coords),
24
24
+
]
25
25
+
.concat()
26
26
+
.try_into()
27
27
+
.unwrap()
28
28
+
}
29
29
+
30
30
+
//could make these use .get() for safe out-of-bounds reads, i suppose
31
31
+
///Never Eat Shredded Wheat
32
32
+
fn adjacent_cardinal<T: Copy>(grid: &[Vec<T>], coords: Point) -> [Option<T>; 4] {
33
33
+
let mut retval = [const { None }; 4];
34
34
+
let (row, col) = (coords.row, coords.col);
35
35
+
36
36
+
if row > 0 {
37
37
+
retval[0] = Some(grid[row - 1][col]) //N
38
38
+
}
39
39
+
if col < grid[0].len() - 1 {
40
40
+
retval[1] = Some(grid[row][col + 1]) //E
41
41
+
}
42
42
+
if row < grid.len() - 1 {
43
43
+
retval[2] = Some(grid[row + 1][col]) //S
44
44
+
}
45
45
+
if col > 0 {
46
46
+
retval[3] = Some(grid[row][col - 1]) //N
47
47
+
}
48
48
+
49
49
+
retval
50
50
+
}
51
51
+
52
52
+
/// Never Eat Shredded Wheat, rotated 45 degrees clockwise
53
53
+
/// AKA northeast, southeast, southwest, northwest
54
54
+
fn adjacent_ordinal<T: Copy>(grid: &[Vec<T>], coords: Point) -> [Option<T>; 4] {
55
55
+
let mut retval = [const { None }; 4];
56
56
+
let (row, col) = (coords.row, coords.col);
57
57
+
58
58
+
if row > 0 && col < grid[0].len() - 1 {
59
59
+
retval[0] = Some(grid[row - 1][col + 1]) //NE
60
60
+
}
61
61
+
if row < grid.len() - 1 && col < grid[0].len() - 1 {
62
62
+
retval[1] = Some(grid[row + 1][col + 1]) //SE
63
63
+
}
64
64
+
if row < grid.len() - 1 && col > 0 {
65
65
+
retval[2] = Some(grid[row + 1][col - 1]) //SW
66
66
+
}
67
67
+
if row > 0 && col > 0 {
68
68
+
retval[3] = Some(grid[row - 1][col - 1]) //NW
69
69
+
}
70
70
+
71
71
+
retval
72
72
+
}