Skip to content

Commit 29d9c39

Browse files
committed
perf: optimize all path finding: reduce memory consumption and improve find using HashSet instead of Vec
1 parent f990327 commit 29d9c39

File tree

3 files changed

+26
-22
lines changed

3 files changed

+26
-22
lines changed

readme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
| [Day 8: Playground](src/solutions/year2025/day08.rs) | ⭐⭐ | 46.993 | 44.599 |
2222
| [Day 9: Movie Theater](src/solutions/year2025/day09.rs) || 0.387 | - |
2323
| [Day 10: Factory](src/solutions/year2025/day10.rs) | | - | - |
24-
| [Day 11: Reactor](src/solutions/year2025/day11.rs) || 0.897 | - |
24+
| [Day 11: Reactor](src/solutions/year2025/day11.rs) || 0.692 | - |
2525

2626
# 2024
2727

@@ -79,7 +79,7 @@
7979
| [Day 20: Pulse Propagation](src/solutions/year2023/day20.rs) | ⭐⭐ | 12.550 | 70.650 |
8080
| [Day 21: Step Counter](src/solutions/year2023/day21.rs) || 300.150 | - |
8181
| [Day 22: Sand Slabs](src/solutions/year2023/day22.rs) | ⭐⭐ | 55.959 | 135.398 |
82-
| [Day 23: A Long Walk](src/solutions/year2023/day23.rs) | ⭐⭐ | 6.943 | 10855.790 |
82+
| [Day 23: A Long Walk](src/solutions/year2023/day23.rs) | ⭐⭐ | 6.987 | 6918.478 |
8383
| [Day 24: Never Tell Me The Odds](src/solutions/year2023/day24.rs) || 2.406 | - |
8484
| [Day 25: Snowverload](src/solutions/year2023/day25.rs) | | - | - |
8585

src/utils/graphs/all_paths.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::utils::graphs::graph::Graph;
2-
use std::collections::{HashMap, VecDeque};
2+
use std::collections::{HashMap, HashSet, VecDeque};
33
use std::hash::Hash;
44

55
pub trait IsEnd<T> {
@@ -24,7 +24,7 @@ pub struct AllPaths<'a, T: 'a> {
2424

2525
impl<'a, T> From<&'a Graph<T>> for AllPaths<'a, T>
2626
where
27-
T: Eq + Hash + Copy + PartialEq + Clone,
27+
T: Eq + Hash + Copy + PartialEq,
2828
{
2929
fn from(graph: &'a Graph<T>) -> Self {
3030
Self::new(move |p: T| graph.neighbours(&p))
@@ -33,15 +33,15 @@ where
3333

3434
impl<'a, T> From<&'a HashMap<T, Vec<T>>> for AllPaths<'a, T>
3535
where
36-
T: Eq + Hash + Copy + PartialEq + Clone,
36+
T: Eq + Hash + Copy + PartialEq,
3737
{
3838
fn from(value: &'a HashMap<T, Vec<T>>) -> Self {
3939
Self::new(move |p: T| value.get(&p).unwrap().to_vec())
4040
}
4141
}
4242
impl<'a, T> AllPaths<'a, T>
4343
where
44-
T: PartialEq + Clone,
44+
T: Eq + Hash + Copy,
4545
{
4646
pub fn new(adjacency: impl Fn(T) -> Vec<T> + 'a) -> Self {
4747
Self {
@@ -54,8 +54,10 @@ where
5454
E: IsEnd<T>,
5555
{
5656
let mut paths: Vec<VecDeque<T>> = Vec::new();
57+
let mut visited = HashSet::new();
58+
let mut path = VecDeque::new();
5759

58-
self.visit(start, &end, Vec::new(), VecDeque::new(), &mut paths);
60+
self.visit(start, &end, &mut visited, &mut path, &mut paths);
5961

6062
paths
6163
}
@@ -64,26 +66,27 @@ where
6466
&self,
6567
from: T,
6668
end: &E,
67-
mut visited: Vec<T>,
68-
mut path: VecDeque<T>,
69+
visited: &mut HashSet<T>,
70+
path: &mut VecDeque<T>,
6971
paths: &mut Vec<VecDeque<T>>,
7072
) where
7173
E: IsEnd<T>,
7274
{
73-
visited.push(from.clone());
74-
path.push_back(from.clone());
75+
visited.insert(from);
76+
path.push_back(from);
7577

7678
if end.is_end(&from) {
7779
paths.push(path.clone());
78-
79-
return;
80-
}
81-
82-
for p in (self.adjacency)(from) {
83-
if !visited.contains(&p) {
84-
self.visit(p, end, visited.clone(), path.clone(), paths);
80+
} else {
81+
for p in (self.adjacency)(from) {
82+
if !visited.contains(&p) {
83+
self.visit(p, end, visited, path, paths);
84+
}
8585
}
8686
}
87+
88+
path.pop_back();
89+
visited.remove(&from);
8790
}
8891
}
8992

@@ -95,7 +98,7 @@ mod tests {
9598
use std::collections::{HashMap, VecDeque};
9699

97100
#[test]
98-
fn generate() {
101+
fn paths() {
99102
let p0 = Point::new(0, 0);
100103
let p1 = Point::new(1, 1);
101104
let p2 = Point::new(2, 2);
@@ -107,9 +110,8 @@ mod tests {
107110
(p2, vec![p0, p1]),
108111
(p3, vec![]),
109112
]);
110-
let adjacency = |p: Point| graph.get(&p).unwrap().to_vec();
111113

112-
let all_paths: AllPaths<Point> = AllPaths::new(adjacency);
114+
let all_paths = AllPaths::from(&graph);
113115

114116
let paths = all_paths.paths(p2, p3);
115117

src/utils/graphs/longest_path.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use crate::utils::graphs::all_paths::AllPaths;
2+
use hash::Hash;
23
use itertools::Itertools;
34
use std::collections::VecDeque;
5+
use std::hash;
46

57
pub struct LongestPath<'a, T> {
68
adjacency: &'a dyn Fn(T) -> Vec<T>,
@@ -9,7 +11,7 @@ pub struct LongestPath<'a, T> {
911

1012
impl<'a, T> LongestPath<'a, T>
1113
where
12-
T: PartialEq + Clone + Copy,
14+
T: PartialEq + Clone + Copy + Eq + Hash,
1315
{
1416
pub fn new(adjacency: &'a dyn Fn(T) -> Vec<T>, cost: &'a dyn Fn(T, T) -> usize) -> Self {
1517
Self { adjacency, cost }

0 commit comments

Comments
 (0)