Reputation: 422
So I have an input 2D array with already placed mines in it:
const input = [
[0, 0, '*'],
['*', 0, 0],
[0, '*', 0]
];
What I need to do it's to output changed 2D array with added number to neighbors, but I don't know how can I elegantly access them.
const mineSweeper = (input) => {
for (let row = 0; row < input.length; row++) {
for (let col = 0; col < input[row].length; col++) {
if (input[row][col] === '*') {
// How can I access neighbors from here elegantly?
}
}
}
}
The output should look like that:
const output = [
[1, 2, '*'],
['*', 3, 2],
[2, '*', 1]
];
Any tip? Thanks.
Upvotes: 1
Views: 868
Reputation: 122047
You can use double nested map
to get each element and then you can create another function that will take current index of row and column and check the close *
of each element.
const input = [
[0, 0, '*'],
['*', 0, 0],
[0, '*', 0]
]
function count(data, i, j) {
let c = 0;
const prevRow = data[i - 1];
const currentRow = data[i]
const nextRow = data[i + 1];
[prevRow, currentRow, nextRow].forEach(row => {
if (row) {
if (row[j - 1] == '*') c++;
if (row[j] == '*') c++;
if (row[j + 1] == '*') c++;
}
})
return c;
}
function update(data) {
return data.map((a, i) => {
return a.map((b, j) => {
return b == '*' ? b : count(data, i, j)
})
})
}
const result = update(input)
console.log(result)
Upvotes: 1
Reputation: 741
const dx = [1, 1, 1, 0, 0, -1, -1, -1];
const dy = [1, 0, -1, 1, -1, 1, 0, -1];
const mineSweeper = (input) => {
for (let row = 0; row < input.length; row++) {
for (let col = 0; col < input[row].length; col++) {
if (input[row][col] === '*') {
for (let i = 0 ; i < 8 ; i++) {
let nr = row + dy[i], nc = col + dx[i];
//check that is within the limits
if (nr >= 0 && nr < input.length && nc >= 0 && nc < input[row].length) {
input[nr][nc]++; //Do what you need with this neighbor
}
}
}
}
}
}
I will explain briefly the logic:
On arrays dx and dy, you store the distance in rows and columns you need to move from a given cell to reach all 8 neighbors.
For example, take the dx[2] = 1
and dy[2] = -1
this means to reach this neighbor 2
you need to move 1 column to the right +1
and one row below -1
.
The if is to check wether the given neighbor exists within the limits of the array.
Upvotes: 1
Reputation: 386578
You could get an array of offsets for getting the right indices and check if the value is a star.
const
getCount = (array, x, y) => offsets
.reduce((c, [i, j]) => c + (array[x + i]?.[y + j] === '*'), 0),
offsets = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]],
input = [[0, 0, '*'], ['*', 0, 0], [0, '*', 0]],
result = input.map((row, i, a) => row.map((v, j) => v || getCount(a, i, j)));
result.forEach(a => console.log(a.join(' ')));
Upvotes: 2
Reputation: 4380
Not the most elegant solution
const input = [
[0, 0, '*'],
['*', 0, 0],
[0, '*', 0],
];
const mineSweeper = input => {
for (let row = 0; row < input.length; row++) {
for (let col = 0; col < input[row].length; col++) {
if (input[row][col] === '*') {
Number.isInteger(input[row - 1] && input[row - 1][col]) && input[row - 1][col]++;
Number.isInteger(input[row] && input[row][col - 1]) && input[row][col - 1]++;
Number.isInteger(input[row + 1] && input[row + 1][col]) && input[row + 1][col]++;
Number.isInteger(input[row] && input[row][col + 1]) && input[row][col + 1]++;
Number.isInteger(input[row - 1] && input[row - 1][col - 1]) && input[row - 1][col - 1]++;
Number.isInteger(input[row + 1] && input[row + 1][col + 1]) && input[row + 1][col + 1]++;
Number.isInteger(input[row - 1] && input[row - 1][col + 1]) && input[row - 1][col + 1]++;
Number.isInteger(input[row + 1] && input[row + 1][col - 1]) && input[row + 1][col - 1]++;
}
}
}
};
mineSweeper(input);
console.log(input);
Upvotes: 0