diff --git a/src/lib.rs b/src/lib.rs index b63c455d..015c9bf8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1464,6 +1464,7 @@ pub mod problem_1911_maximum_alternating_subsequence_sum; pub mod problem_1913_maximum_product_difference_between_two_pairs; pub mod problem_1915_number_of_wonderful_substrings; pub mod problem_1920_build_array_from_permutation; +pub mod problem_1926_nearest_exit_from_entrance_in_maze; #[cfg(test)] mod test_utilities; diff --git a/src/problem_1926_nearest_exit_from_entrance_in_maze/bfs.rs b/src/problem_1926_nearest_exit_from_entrance_in_maze/bfs.rs new file mode 100644 index 00000000..16d418a3 --- /dev/null +++ b/src/problem_1926_nearest_exit_from_entrance_in_maze/bfs.rs @@ -0,0 +1,80 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +use std::collections::VecDeque; +use std::convert::TryInto; + +impl Solution { + pub fn nearest_exit(maze: Vec>, entrance: Vec) -> i32 { + let mut maze = maze; + let [y, x]: [_; 2] = entrance.try_into().ok().unwrap(); + let y = y as u8; + let x = x as u8; + + let mut queue = VecDeque::new(); + + maze[usize::from(y)][usize::from(x)] = '\0'; + + for neighbor in [(y.wrapping_sub(1), x), (y, x.wrapping_sub(1)), (y, x + 1), (y + 1, x)] { + if let Some(state) = maze + .get_mut(usize::from(neighbor.0)) + .and_then(|row| row.get_mut(usize::from(neighbor.1))) + { + if *state == '.' { + *state = '\0'; + + queue.push_back(neighbor); + } + } + } + + let mut result = 1; + + while !queue.is_empty() { + for _ in 0..queue.len() { + let node = queue.pop_front().unwrap(); + + for neighbor in [ + (node.0.wrapping_sub(1), node.1), + (node.0, node.1.wrapping_sub(1)), + (node.0, node.1 + 1), + (node.0 + 1, node.1), + ] { + if let Some(state) = maze + .get_mut(usize::from(neighbor.0)) + .and_then(|row| row.get_mut(usize::from(neighbor.1))) + { + if *state == '.' { + *state = '\0'; + + queue.push_back(neighbor); + } + } else { + return result; + } + } + } + + result += 1; + } + + -1 + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn nearest_exit(maze: Vec>, entrance: Vec) -> i32 { + Self::nearest_exit(maze, entrance) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_1926_nearest_exit_from_entrance_in_maze/mod.rs b/src/problem_1926_nearest_exit_from_entrance_in_maze/mod.rs new file mode 100644 index 00000000..ecaf3bd5 --- /dev/null +++ b/src/problem_1926_nearest_exit_from_entrance_in_maze/mod.rs @@ -0,0 +1,25 @@ +pub mod bfs; + +pub trait Solution { + fn nearest_exit(maze: Vec>, entrance: Vec) -> i32; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [ + ((&["++.+", "...+", "+++."] as &[_], [1, 2]), 1), + ((&["+++", "...", "+++"], [1, 0]), 2), + ((&[".+"], [0, 0]), -1), + ]; + + for ((maze, entrance), expected) in test_cases { + assert_eq!( + S::nearest_exit(maze.iter().map(|row| row.chars().collect()).collect(), entrance.into()), + expected, + ); + } + } +}