-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
lee_breadth_first_search.rs
117 lines (105 loc) · 3.39 KB
/
lee_breadth_first_search.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
use std::collections::VecDeque;
// All four potential movements from a cell are listed here.
fn validate(matrix: &[Vec<i32>], visited: &[Vec<bool>], row: isize, col: isize) -> bool {
// Check if it is possible to move to the position (row, col) from the current cell.
let (row, col) = (row as usize, col as usize);
row < matrix.len() && col < matrix[0].len() && matrix[row][col] == 1 && !visited[row][col]
}
pub fn lee(matrix: Vec<Vec<i32>>, source: (usize, usize), destination: (usize, usize)) -> isize {
const ROW: [isize; 4] = [-1, 0, 0, 1];
const COL: [isize; 4] = [0, -1, 1, 0];
let (i, j) = source;
let (x, y) = destination;
// Base case: invalid input
if matrix.is_empty() || matrix[i][j] == 0 || matrix[x][y] == 0 {
return -1;
}
let (m, n) = (matrix.len(), matrix[0].len());
let mut visited = vec![vec![false; n]; m];
let mut q = VecDeque::new();
visited[i][j] = true;
q.push_back((i, j, 0));
let mut min_dist = isize::MAX;
// Loop until the queue is empty
while let Some((i, j, dist)) = q.pop_front() {
if i == x && j == y {
// If the destination is found, update `min_dist` and stop
min_dist = dist;
break;
}
// Check for all four possible movements from the current cell
for k in 0..ROW.len() {
let row = i as isize + ROW[k];
let col = j as isize + COL[k];
if validate(&matrix, &visited, row, col) {
// Mark the next cell as visited and enqueue it
let (row, col) = (row as usize, col as usize);
visited[row][col] = true;
q.push_back((row, col, dist + 1));
}
}
}
if min_dist != isize::MAX {
min_dist
} else {
-1
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_lee_exists() {
let mat: Vec<Vec<i32>> = vec![
vec![1, 0, 1, 1, 1],
vec![1, 0, 1, 0, 1],
vec![1, 1, 1, 0, 1],
vec![0, 0, 0, 0, 1],
vec![1, 1, 1, 0, 1],
];
let source = (0, 0);
let dest = (2, 1);
assert_eq!(lee(mat, source, dest), 3);
}
#[test]
fn test_lee_does_not_exist() {
let mat: Vec<Vec<i32>> = vec![
vec![1, 0, 1, 1, 1],
vec![1, 0, 0, 0, 1],
vec![1, 1, 1, 0, 1],
vec![0, 0, 0, 0, 1],
vec![1, 1, 1, 0, 1],
];
let source = (0, 0);
let dest = (3, 4);
assert_eq!(lee(mat, source, dest), -1);
}
#[test]
fn test_source_equals_destination() {
let mat: Vec<Vec<i32>> = vec![
vec![1, 0, 1, 1, 1],
vec![1, 0, 1, 0, 1],
vec![1, 1, 1, 0, 1],
vec![0, 0, 0, 0, 1],
vec![1, 1, 1, 0, 1],
];
let source = (2, 1);
let dest = (2, 1);
assert_eq!(lee(mat, source, dest), 0);
}
#[test]
fn test_lee_exists_2() {
let mat: Vec<Vec<i32>> = vec![
vec![1, 1, 1, 1, 1, 0, 0],
vec![1, 1, 1, 1, 1, 1, 0],
vec![1, 0, 1, 0, 1, 1, 1],
vec![1, 1, 1, 1, 1, 0, 1],
vec![0, 0, 0, 1, 0, 0, 0],
vec![1, 0, 1, 1, 1, 0, 0],
vec![0, 0, 0, 0, 1, 0, 0],
];
let source = (0, 0);
let dest = (3, 2);
assert_eq!(lee(mat, source, dest), 5);
}
}