tangled
alpha
login
or
join now
nove.dev
/
aoc-2024
0
fork
atom
retroactive, to derust my rust
0
fork
atom
overview
issues
pulls
pipelines
day10 part2
nove.dev
3 months ago
44f5223e
fecde968
+97
-10
5 changed files
expand all
collapse all
unified
split
input
day10_simple.test.txt
day10_simple2.test.txt
src
day10.rs
lib.rs
spatial.rs
+7
input/day10_simple.test.txt
···
1
1
+
..90..9
2
2
+
...1.98
3
3
+
...2..7
4
4
+
6543456
5
5
+
765.987
6
6
+
876....
7
7
+
987....
+7
input/day10_simple2.test.txt
···
1
1
+
.....0.
2
2
+
..4321.
3
3
+
..5..2.
4
4
+
..6543.
5
5
+
..7..4.
6
6
+
..8765.
7
7
+
..9....
+25
-3
src/day10.rs
···
1
1
-
use crate::spatial::{Point, adjacent_cardinal, adjacent_cardinal_points, all_coords, flood};
1
1
+
use itertools::Itertools;
2
2
+
3
3
+
use crate::spatial::{
4
4
+
Point, adjacent_cardinal, adjacent_cardinal_points, all_coords, flood, paths_to_each_point,
5
5
+
print_grid,
6
6
+
};
2
7
use std::collections::{BTreeSet, HashMap};
3
8
4
9
pub fn day10_part1(input: &str) -> String {
···
13
18
}
14
19
15
20
pub fn day10_part2(input: &str) -> String {
16
16
-
todo!()
21
21
+
let topomap = parse(input);
22
22
+
let digraph = topomap_to_digraph(&topomap);
23
23
+
let ratings = all_coords(topomap[0].len(), topomap.len())
24
24
+
.filter(|pt| topomap[pt.row][pt.col] == 0)
25
25
+
.map(|pt| paths_to_each_point(&digraph, pt))
26
26
+
.filter(|grid| {
27
27
+
all_coords(topomap[0].len(), topomap.len())
28
28
+
.any(|pt| topomap[pt.row][pt.col] == 9 && !grid[pt.row][pt.col].is_empty())
29
29
+
})
30
30
+
.map(|grid| {
31
31
+
all_coords(topomap[0].len(), topomap.len())
32
32
+
.filter(|pt| topomap[pt.row][pt.col] == 9)
33
33
+
.map(|pt| grid[pt.row][pt.col].len())
34
34
+
.sum::<usize>()
35
35
+
})
36
36
+
.collect_vec();
37
37
+
dbg!(&ratings);
38
38
+
ratings.iter().sum::<usize>().to_string()
17
39
}
18
40
19
41
fn parse(input: &str) -> Vec<Vec<u8>> {
···
21
43
.lines()
22
44
.map(|line| {
23
45
line.chars()
24
24
-
.map(|c| c.to_digit(10).unwrap() as u8)
46
46
+
.map(|c| c.to_digit(10).unwrap_or(11) as u8)
25
47
.collect()
26
48
})
27
49
.collect()
+11
-7
src/lib.rs
···
359
359
let result = day10::day10_part1(include_str!("../input/day10.txt"));
360
360
assert_eq!(result, "820");
361
361
}
362
362
-
// #[test]
363
363
-
// fn day10_part2_test() {
364
364
-
// let test_result = day10::day10_part2(include_str!("../input/day10.test.txt"));
365
365
-
// assert_eq!(test_result, "2858");
366
366
-
// // let result = day10::day10_part2(include_str!("../input/day10.txt"));
367
367
-
// // assert_eq!(result, "6476642796832");
368
368
-
// }
362
362
+
#[test]
363
363
+
fn day10_part2_test() {
364
364
+
let test_result = day10::day10_part2(include_str!("../input/day10_simple2.test.txt"));
365
365
+
assert_eq!(test_result, "3");
366
366
+
let test_result = day10::day10_part2(include_str!("../input/day10_simple.test.txt"));
367
367
+
assert_eq!(test_result, "13");
368
368
+
let test_result = day10::day10_part2(include_str!("../input/day10.test.txt"));
369
369
+
assert_eq!(test_result, "81");
370
370
+
let result = day10::day10_part2(include_str!("../input/day10.txt"));
371
371
+
assert_eq!(result, "1786");
372
372
+
}
369
373
370
374
#[test]
371
375
fn day9_part1_test() {
+47
src/spatial.rs
···
7
7
pub row: usize,
8
8
pub col: usize,
9
9
}
10
10
+
11
11
+
impl ToString for Point {
12
12
+
fn to_string(&self) -> String {
13
13
+
format!("({}, {})", self.row, self.col)
14
14
+
}
15
15
+
}
16
16
+
10
17
pub fn all_coords(width: usize, height: usize) -> impl Iterator<Item = Point> {
11
18
(0..height)
12
19
.cartesian_product(0..width)
···
69
76
70
77
reachable
71
78
}
79
79
+
80
80
+
//2d spatial dag
81
81
+
pub fn paths_to_each_point(
82
82
+
digraph: &[Vec<Vec<Point>>],
83
83
+
start: Point,
84
84
+
) -> Vec<Vec<BTreeSet<Vec<Point>>>> {
85
85
+
let mut paths_to_each_point = vec![vec![BTreeSet::new(); digraph.len()]; digraph[0].len()];
86
86
+
paths_to_each_point[start.row][start.col] = BTreeSet::from_iter([vec![start]]);
87
87
+
let mut frontier = BTreeSet::from_iter([start]);
88
88
+
89
89
+
while let Some(cursor) = frontier.pop_first() {
90
90
+
println!("cursor is at ({}, {})", cursor.row, cursor.col);
91
91
+
for point in &digraph[cursor.row][cursor.col] {
92
92
+
println!("dealing with adjacent point ({}, {})", point.row, point.col);
93
93
+
frontier.insert(*point);
94
94
+
println!(
95
95
+
"frontier now has {} points: {}",
96
96
+
frontier.len(),
97
97
+
frontier.iter().map(|pt| pt.to_string()).join(", ")
98
98
+
);
99
99
+
let paths_to_new_point = paths_to_each_point[cursor.row][cursor.col].clone();
100
100
+
for mut path in paths_to_new_point {
101
101
+
path.push(*point);
102
102
+
paths_to_each_point[point.row][point.col].insert(path);
103
103
+
}
104
104
+
}
105
105
+
}
106
106
+
107
107
+
dbg!(paths_to_each_point.len());
108
108
+
paths_to_each_point
109
109
+
}
110
110
+
111
111
+
pub fn print_grid<T: ToString>(paths: Vec<Vec<T>>) -> Vec<Vec<T>> {
112
112
+
let s = paths
113
113
+
.iter()
114
114
+
.map(|row| row.iter().map(|count| count.to_string()).join(""))
115
115
+
.join("\n");
116
116
+
println!("{s}\n");
117
117
+
paths
118
118
+
}