JSFiddle - React, Tailwind, and code Playground
by also
JavaScript
function *makeBorderIter(matrix) {
const width = matrix[0].length;
const height = matrix.length;
for (const y of [0, height - 1]) {
for (let x = 0; x < width; x++) {
yield [x, y];
}
}
for (const x of [0, width - 1]) {
for (let y = 0; y < height; y++) {
yield [x, y];
}
}
}
function get(matrix, [x, y]) {
return matrix[y] ? matrix[y][x] : undefined;
}
function *getAdjacentBlack(matrix, [x, y]) {
const result = [];
for (const [xx, yy] of [[-1, 0], [1, 0], [0, -1], [0, 1]]) {
const pos = [x + xx, y + yy];
if (get(matrix, pos) === 1) {
yield pos;
}
}
}
const matrix = [
[0, 0, 1, 0],
[1, 0, 1, 1],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 0]
];
const borderIslands = {};
function isBorderIsland(pos) {
return get(borderIslands, pos);
}
function markAsBorderIsland([x, y]) {
if (borderIslands[y] != null) {
borderIslands[y][x] = true
} else {
borderIslands[y] = {
[x]: true
};
}
}
for (const pos of makeBorderIter(matrix)) {
// skip if white
if (get(matrix, pos) === 0) {
continue;
}
// mark black border as border island
markAsBorderIsland(pos);
const adjacent = [...getAdjacentBlack(matrix, pos)];
// bfs of adjacent black coords
while (adjacent.length) {
const pos = adjacent.shift();
// skip if we've already processed it
if (isBorderIsland(pos)) {
continue;
}
adjacent.push(...getAdjacentBlack(matrix, pos));
markAsBorderIsland(pos);
}
}
// find all black coords that aren't connected to a border island
for (const y in matrix) {
for (const x in matrix[y]) {
if (matrix[y][x] === 1 && !isBorderIsland([x, y])) {
matrix[y][x] = null;
}
}
}
console.log(matrix);