Skip to content

Commit 83ae16d

Browse files
Add Lee Algorithm (#583)
1 parent cb1b83d commit 83ae16d

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed

src/graph/lee.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
use std::collections::VecDeque;
2+
3+
// All four potential movements from a cell are listed here.
4+
5+
fn validate(matrix: &[Vec<i32>], visited: &[Vec<bool>], row: isize, col: isize) -> bool {
6+
// Check if it is possible to move to the position (row, col) from the current cell.
7+
let (row, col) = (row as usize, col as usize);
8+
row < matrix.len() && col < matrix[0].len() && matrix[row][col] == 1 && !visited[row][col]
9+
}
10+
11+
pub fn lee(matrix: Vec<Vec<i32>>, source: (usize, usize), destination: (usize, usize)) -> isize {
12+
const ROW: [isize; 4] = [-1, 0, 0, 1];
13+
const COL: [isize; 4] = [0, -1, 1, 0];
14+
let (i, j) = source;
15+
let (x, y) = destination;
16+
17+
// Base case: invalid input
18+
if matrix.is_empty() || matrix[i][j] == 0 || matrix[x][y] == 0 {
19+
return -1;
20+
}
21+
22+
let (m, n) = (matrix.len(), matrix[0].len());
23+
let mut visited = vec![vec![false; n]; m];
24+
let mut q = VecDeque::new();
25+
visited[i][j] = true;
26+
q.push_back((i, j, 0));
27+
let mut min_dist = isize::MAX;
28+
29+
// Loop until the queue is empty
30+
while let Some((i, j, dist)) = q.pop_front() {
31+
if i == x && j == y {
32+
// If the destination is found, update `min_dist` and stop
33+
min_dist = dist;
34+
break;
35+
}
36+
37+
// Check for all four possible movements from the current cell
38+
for k in 0..ROW.len() {
39+
let row = i as isize + ROW[k];
40+
let col = j as isize + COL[k];
41+
if validate(&matrix, &visited, row, col) {
42+
// Mark the next cell as visited and enqueue it
43+
let (row, col) = (row as usize, col as usize);
44+
visited[row][col] = true;
45+
q.push_back((row, col, dist + 1));
46+
}
47+
}
48+
}
49+
50+
if min_dist != isize::MAX {
51+
min_dist
52+
} else {
53+
-1
54+
}
55+
}
56+
57+
#[cfg(test)]
58+
mod tests {
59+
use super::*;
60+
#[test]
61+
fn test_lee_exists() {
62+
let mat: Vec<Vec<i32>> = vec![
63+
vec![1, 0, 1, 1, 1],
64+
vec![1, 0, 1, 0, 1],
65+
vec![1, 1, 1, 0, 1],
66+
vec![0, 0, 0, 0, 1],
67+
vec![1, 1, 1, 0, 1],
68+
];
69+
let source = (0, 0);
70+
let dest = (2, 1);
71+
assert_eq!(lee(mat, source, dest), 3);
72+
}
73+
74+
#[test]
75+
fn test_lee_does_not_exist() {
76+
let mat: Vec<Vec<i32>> = vec![
77+
vec![1, 0, 1, 1, 1],
78+
vec![1, 0, 0, 0, 1],
79+
vec![1, 1, 1, 0, 1],
80+
vec![0, 0, 0, 0, 1],
81+
vec![1, 1, 1, 0, 1],
82+
];
83+
let source = (0, 0);
84+
let dest = (3, 4);
85+
assert_eq!(lee(mat, source, dest), -1);
86+
}
87+
88+
#[test]
89+
fn test_source_equals_destination() {
90+
let mat: Vec<Vec<i32>> = vec![
91+
vec![1, 0, 1, 1, 1],
92+
vec![1, 0, 1, 0, 1],
93+
vec![1, 1, 1, 0, 1],
94+
vec![0, 0, 0, 0, 1],
95+
vec![1, 1, 1, 0, 1],
96+
];
97+
let source = (2, 1);
98+
let dest = (2, 1);
99+
assert_eq!(lee(mat, source, dest), 0);
100+
}
101+
102+
#[test]
103+
fn test_lee_exists_2() {
104+
let mat: Vec<Vec<i32>> = vec![
105+
vec![1, 1, 1, 1, 1, 0, 0],
106+
vec![1, 1, 1, 1, 1, 1, 0],
107+
vec![1, 0, 1, 0, 1, 1, 1],
108+
vec![1, 1, 1, 1, 1, 0, 1],
109+
vec![0, 0, 0, 1, 0, 0, 0],
110+
vec![1, 0, 1, 1, 1, 0, 0],
111+
vec![0, 0, 0, 0, 1, 0, 0],
112+
];
113+
let source = (0, 0);
114+
let dest = (3, 2);
115+
assert_eq!(lee(mat, source, dest), 5);
116+
}
117+
}

src/graph/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ mod ford_fulkerson;
1414
mod graph_enumeration;
1515
mod heavy_light_decomposition;
1616
mod kosaraju;
17+
mod lee;
1718
mod lowest_common_ancestor;
1819
mod minimum_spanning_tree;
1920
mod prim;
@@ -39,6 +40,7 @@ pub use self::ford_fulkerson::ford_fulkerson;
3940
pub use self::graph_enumeration::enumerate_graph;
4041
pub use self::heavy_light_decomposition::HeavyLightDecomposition;
4142
pub use self::kosaraju::kosaraju;
43+
pub use self::lee::lee;
4244
pub use self::lowest_common_ancestor::{LowestCommonAncestorOffline, LowestCommonAncestorOnline};
4345
pub use self::minimum_spanning_tree::kruskal;
4446
pub use self::prim::{prim, prim_with_start};

0 commit comments

Comments
 (0)