
https://school.programmers.co.kr/learn/courses/30/lessons/120866
function solution(board) {
const n = board.length;
const flatten = board.flat();
for (let i = 0; i < n*n; i++) {
if (flatten[i] === 1) {
const dangerZone = [i-1-n, i-n, i+1-n, i-1, i+1, i-1+n, i+n, i+1+n].filter((v) => v >= 0 && v < n*n);
dangerZone.forEach((v) => {
if (!flatten[v]) {
flatten[v] = "X";
}
})
}
}
return flatten.filter((v) => !v).length;
}
✔ "2차원으로 된 배열을 1차원으로 바꾸면 훨씬 더 수월하게 해결할 수 있지 않을까?" 하는 생각으로 flat() 메소드를 통해 board를 평탄화시킴
✔ 폭탄의 위치를 제외한 나머지 8칸에 대해 0 미만이거나 n*n 이상의 인덱스를 가지는 부분은 배열의 범위에 벗어나기 때문에 제외
✔ filter된 칸 중 0인 부분만 위험 지역을 뜻하는 X로 마킹
❗ 결과는... 테스트 케이스 7번을 통과하지 못해서 실패😭
지뢰가 왼쪽 끝이나 오른쪽 끝에 있을 경우에 문제가 발생한다.
예를 들어,
1 1 0 0
1 1 0 0
0 0 0 0
0 0 0 0
의 경우 (0,0)에 위치한 1의 경우 dangerZone이 [-5, -4, -3, -1, 1, 3, 4, 5]가 되는데, (0,0)의 왼쪽 아래의 경우 board에서는 배열의 범위를 벗어나게 되지만 평탄화시켰을 때는 i-1+n에 의해 flatten의 3번째 인덱스를 가리키게 된다.
따라서 쌩뚱맞은 위치에 위한 flatten[3]에 X가 마킹이 된다.
즉, 1차원과 2차원 배열의 기본적인 특성 차이를 망각해버려서 생겨버린 문제였다..
결론은, 그냥 정석대로 "2차원 배열로 풀자!" 였다.😅
function solution(board) {
const n = board.length;
for (let r = 0; r < n; r++) {
for (let c = 0; c < n; c++) {
if (board[r][c] === 1) {
const dangerZone = [
[r-1, c-1], [r-1, c], [r-1, c+1],
[r, c-1], [r, c+1],
[r+1, c-1], [r+1, c], [r+1, c+1]
];
dangerZone
.filter((v) => (v[0] >= 0 && v[0] < n) && (v[1] >= 0 && v[1] < n))
.forEach((v) => {
if (!board[v[0]][v[1]]) {
board[v[0]][v[1]] = "X";
}
});
}
}
}
return board.flat().filter((v) => !v).length;
}
✔ 위험지역의 좌표들을 dangerZone 2차원 배열에 저장
✔ filter를 통해 배열의 범위 밖의 좌표를 제외
✔ flat를 통해 1차원으로 펼친 다음 0의 개수를 리턴
function solution(board) {
let outside = [[-1,0], [-1,-1], [-1,1], [0,-1],[0,1],[1,0], [1,-1], [1,1]];
let safezone = 0;
board.forEach((row, y, self) => row.forEach((it, x) => {
if (it === 1) return false;
return outside.some(([oy, ox]) => !!self[oy + y]?.[ox + x])
? false : safezone++;
}));
return safezone;
}
되게 풀이가 간소화된 방법인 것 같아서 가져와봤다.
✔ 나처럼 위험지역의 좌표를 직접 표현하지 않고 outside에 상대적인 벡터값을 저장하였다.
✔ ?.(optional chaining)을 사용하여 self[oy + y]가 존재하지 않으면 아예 self[oy + y]?.[ox + x]가 undefined가 되도록! -> 에러 방지
✔ 지뢰를 기준으로 주변을 보는게 아닌 주변에 지뢰가 있는지 확인하는 접근 방식 -> 아주 참신하다.
✔ forEach의 세 번째 인자로 자기 자신, 즉 board를 가져올 수 있다. 여기에 변경을 가하게 되면 원본도 변경이 적용된다는 점!