Skip to content

Commit

Permalink
Add problem 1905: Count Sub Islands
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed May 17, 2024
1 parent 55c3689 commit d11ebf3
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1416,6 +1416,7 @@ pub mod problem_1899_merge_triplets_to_form_target_triplet;
pub mod problem_1901_find_a_peak_element_ii;
pub mod problem_1903_largest_odd_number_in_string;
pub mod problem_1904_the_number_of_full_rounds_you_have_played;
pub mod problem_1905_count_sub_islands;
pub mod problem_1906_minimum_absolute_difference_queries;
pub mod problem_1909_remove_one_element_to_make_the_array_strictly_increasing;
pub mod problem_1910_remove_all_occurrences_of_a_substring;
Expand Down
66 changes: 66 additions & 0 deletions src/problem_1905_count_sub_islands/bfs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
pub struct Solution;

// ------------------------------------------------------ snip ------------------------------------------------------ //

use std::collections::VecDeque;

impl Solution {
pub fn count_sub_islands(grid1: Vec<Vec<i32>>, grid2: Vec<Vec<i32>>) -> i32 {
let mut grid2 = grid2;
let rows = grid1.len();
let columns = grid1.first().map_or(0, Vec::len);
let mut result = 0;
let mut queue = VecDeque::new();

for y in 0..rows {
for x in 0..columns {
if let state @ 1 = &mut grid2[y][x] {
*state = 0;

let mut is_sub_island = grid1[y][x] != 0;
let mut y = y;
let mut x = x;

loop {
for next in [(y.wrapping_sub(1), x), (y, x.wrapping_sub(1)), (y, x + 1), (y + 1, x)] {
if let Some(state @ 1) = grid2.get_mut(next.0).and_then(|row| row.get_mut(next.1)) {
*state = 0;

is_sub_island &= grid1[next.0][next.1] != 0;

queue.push_back((next.0 as u16, next.1 as u16));
}
}

if let Some(next) = queue.pop_front() {
y = usize::from(next.0);
x = usize::from(next.1);
} else {
break;
}
}

result += i32::from(is_sub_island);
}
}
}

result
}
}

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl super::Solution for Solution {
fn count_sub_islands(grid1: Vec<Vec<i32>>, grid2: Vec<Vec<i32>>) -> i32 {
Self::count_sub_islands(grid1, grid2)
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}
87 changes: 87 additions & 0 deletions src/problem_1905_count_sub_islands/bfs_2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
pub struct Solution;

// ------------------------------------------------------ snip ------------------------------------------------------ //

use std::collections::VecDeque;

impl Solution {
pub fn count_sub_islands(grid1: Vec<Vec<i32>>, grid2: Vec<Vec<i32>>) -> i32 {
let rows = grid1.len();
let columns = grid1.first().map_or(0, Vec::len);

assert!(rows <= 500);
assert!(columns <= 500);

let mut grid = vec![0_u8; columns * rows].into_boxed_slice();
let mut grid_writer = grid.iter_mut();

for (row_1, row_2) in grid1.into_iter().zip(grid2) {
for ((value_1, value_2), target) in row_1.into_iter().zip(row_2).zip(&mut grid_writer) {
*target = ((value_1 as u8) << 1) | value_2 as u8;
}
}

let mut result = 0;
let mut queue = VecDeque::new();

for y in 0..rows {
for x in 0..columns {
let state = &mut grid[columns * y + x];

if *state & 1 != 0 {
let mut is_sub_island = (*state >> 1) != 0;

*state = 0;

let mut y = y;
let mut x = x;

loop {
for next in [(y.wrapping_sub(1), x), (y, x.wrapping_sub(1)), (y, x + 1), (y + 1, x)] {
if next.1 < columns {
let next_index = columns.wrapping_mul(next.0).wrapping_add(next.1);

if let Some(state) = grid.get_mut(next_index) {
if *state & 1 != 0 {
is_sub_island &= (*state >> 1) != 0;

*state = 0;

queue.push_back((next.0 as u16, next.1 as u16));
}
}
}
}

if let Some(next) = queue.pop_front() {
y = usize::from(next.0);
x = usize::from(next.1);
} else {
break;
}
}

result += i32::from(is_sub_island);
}
}
}

result
}
}

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl super::Solution for Solution {
fn count_sub_islands(grid1: Vec<Vec<i32>>, grid2: Vec<Vec<i32>>) -> i32 {
Self::count_sub_islands(grid1, grid2)
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}
59 changes: 59 additions & 0 deletions src/problem_1905_count_sub_islands/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
pub mod bfs;
pub mod bfs_2;

pub trait Solution {
fn count_sub_islands(grid1: Vec<Vec<i32>>, grid2: Vec<Vec<i32>>) -> i32;
}

#[cfg(test)]
mod tests {
use super::Solution;
use crate::test_utilities::Matrix;

pub fn run<S: Solution>() {
let test_cases = [
(
(
&[
[1, 1, 1, 0, 0],
[0, 1, 1, 1, 1],
[0, 0, 0, 0, 0],
[1, 0, 0, 0, 0],
[1, 1, 0, 1, 1],
] as &dyn Matrix<_>,
&[
[1, 1, 1, 0, 0],
[0, 0, 1, 1, 1],
[0, 1, 0, 0, 0],
[1, 0, 1, 1, 0],
[0, 1, 0, 1, 0],
] as &dyn Matrix<_>,
),
3,
),
(
(
&[
[1, 0, 1, 0, 1],
[1, 1, 1, 1, 1],
[0, 0, 0, 0, 0],
[1, 1, 1, 1, 1],
[1, 0, 1, 0, 1],
],
&[
[0, 0, 0, 0, 0],
[1, 1, 1, 1, 1],
[0, 1, 0, 1, 0],
[0, 1, 0, 1, 0],
[1, 0, 0, 0, 1],
],
),
2,
),
];

for ((grid1, grid2), expected) in test_cases {
assert_eq!(S::count_sub_islands(grid1.to_vec(), grid2.to_vec()), expected);
}
}
}

0 comments on commit d11ebf3

Please sign in to comment.