Last active
February 2, 2023 03:51
-
-
Save daftAnorak/2554c2e50817347652fc10cfeea567dd to your computer and use it in GitHub Desktop.
Code Exercise for JS Role - Remove islands from an image matrix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* creates key from coordinates (for mapping) | |
* @param {number} r - row number | |
* @param {number} c - column number | |
* | |
* @returns {string} string key | |
*/ | |
const toKey = (r, c) => `${r}|${c}`; | |
/** | |
* converts string key back to rows/column | |
* | |
* @param {string} str - string key | |
* | |
* @returns {[number, number]} - row and column | |
*/ | |
const toCoord = (str) => str.split('|').map(Number); | |
/** | |
* Determinitate for point being on the border of a given matrix | |
* | |
* @param {number[][]} matrix | |
* @param {number} row | |
* @param {number} col | |
* | |
* @returns {boolean} is row/col combo a border point in matrix | |
*/ | |
function isBorderPoint(matrix, row, col) { | |
return !row || | |
!col || | |
row === matrix.length - 1 || | |
col === matrix[0].length - 1; | |
} | |
/** | |
* Recursive connector lookup which determines if given point (rows/cols) is | |
* NOT an island connection. | |
* | |
* @param {number[][]} matrix | |
* @param {number} row | |
* @param {number} col | |
* @param {object} current | |
* | |
* @returns {void} updates 'current' map | |
*/ | |
function getConnections(matrix, row, col, current) { | |
// add key | |
current[toKey(row, col)] = true; | |
const connections = [ | |
// top | |
[row - 1, col], | |
// right | |
[row, col + 1], | |
// bottom | |
[row + 1, col], | |
// left | |
[row, col - 1], | |
]; | |
connections | |
.filter(([r, c]) => matrix[r] && matrix[r][c] && !current[toKey(r, c)]) | |
.forEach(([r, c]) => { | |
getConnections(matrix, r, c, current); | |
}); | |
} | |
/** | |
* Recreates image matrix (1 and 0), removing 1s which are islands; 1s not | |
* connected continually via other 1s to the border | |
* | |
* @example | |
* 0 0 0 1 0 | |
* 0 0 0 1 0 | |
* 1 1 0 0 0 | |
* 1 0 1 1 0 | |
* 1 0 0 0 0 | |
* | |
* becomes: | |
* | |
* 0 0 0 1 0 | |
* 0 0 0 1 0 | |
* 1 1 0 0 0 | |
* 1 0 0 0 0 | |
* 1 0 0 0 0 | |
* | |
* @param {number[][]} imageMatrix - original image matrix | |
* | |
* @returns {number[][]} new image matrix without isolated 1s (islands) | |
*/ | |
function removeIslands(imageMatrix) { | |
const oneCoords = {}; | |
const newMatrix = []; | |
let rows = imageMatrix.length; | |
// loop through image matrix, creating new matrix (all zeroes) | |
while (rows--) { | |
let cols = imageMatrix[rows].length; | |
newMatrix[rows] = []; | |
while (cols--) { | |
newMatrix[rows][cols] = 0; | |
if (imageMatrix[rows][cols] && isBorderPoint(imageMatrix, rows, cols)) { | |
// pass oneCoords to determine which coords should remain 1 | |
getConnections(imageMatrix, rows, cols, oneCoords); | |
} | |
} | |
} | |
// loop through oneCoords to reimplement 1s we wish to keep | |
Object.keys(oneCoords).forEach((key) => { | |
const [r, c] = toCoord(key); | |
newMatrix[r][c] = 1; | |
}); | |
return newMatrix; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment