자료구조 및 알고리즘/JavaScript Practice

JS Practice) 프로그래머스 : 안전지대

Ryomi 2023. 5. 2. 09:55
728x90
반응형

 

 

안전지대

문제설명 :

다음 그림과 같이 지뢰가 있는 지역과 지뢰에 인접한 위, 아래, 좌, 우 대각선 칸을 모두 위험지역으로 분류합니다.


지뢰는 2차원 배열 board에 1로 표시되어 있고 board에는 지뢰가 매설된 지역 1과, 지뢰가 없는 지역 0만 존재합니다.
지뢰가 매설된 지역의 지도 board가 매개변수로 주어질 때, 안전한 지역의 칸 수를 return 하도록 solution 함수를 완성해 주세요.

 

제한 사항

  • board는 n * n 배열입니다.
  • 1 ≤ n ≤ 100
  • 지뢰는 1로 표시되어 있습니다.
  • board에는 지뢰가 있는 지역 1과 지뢰가 없는 지역 0만 존재합니다.

 
입출력 예

boardreturn
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0]]16
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 1, 0], [0, 0, 0, 0, 0]]13
[[1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1]]0

 
첫 번째 접근
: 이중 배열이니 두 개의 for 문을 돌렸다. 먼저 board의 전체 칸수를 구했다. 그리고 위험 구간의 정보를 넣을 배열을 만들었다. 이중 for문을 돌려 1이 나오면 거기서 다시 이중 for 문을 돌렸다. 예시를 보면 1의 위치가 (x, y)일 때, (x-1, y-1) ~ (x+1, y+1)까지 총 9칸의 영역이 danger에 속한다. 단, 해당 영역이 board 영역 내에 있을 경우에면 dangerZone 배열에 좌표정보를 push 하기 위해 dangerZone에서 넘어가지 않는 영역인지를 board [0]. length를 사용해 확인해 주었다. 

function solution(board) {
    let zone = Math.pow(board[0].length, 2)
    let dangerZone = []
    
    for(let i = 0; i < board[0].length; i++){
        for(let j = 0; j < board[0].length; j++){
            if(board[i][j] === 1){
                for(let n = i-1; n <= i+1; n++){
                    for(let m = j-1; m <= j+1; m++){
                        m < board[0].length && n < board[0].length ? dangerZone.push(`${n}, ${m}`) : ""
                    }
                }
            }
        }
    }
    dangerZone = new Set(dangerZone)
    return zone - dangerZone.size
}

 
 
두 번째 접근
: 틀렸다. 마지막 테스트 케이스가 통과하지 못했다. dangerZone을 console.log() 해보니, 음수가 나오는 경우가 있었다. board 영역에서 왼쪽이나 위쪽으로 영역이 벗어날 때의 예외처리를 하지 않았다. 추가로 m, n이 -1보다 크다는 조건을 추가해 주었다. 문제를 해결했다. 

function solution(board) {
    let zone = Math.pow(board[0].length, 2)
    let dangerZone = []
    
    for(let i = 0; i < board[0].length; i++){
        for(let j = 0; j < board[0].length; j++){
            if(board[i][j] === 1){
                for(let n = i-1; n <= i+1; n++){
                    for(let m = j-1; m <= j+1; m++){
                        m > -1 && n > -1 && m < board[0].length && n < board[0].length ? dangerZone.push(`${n}, ${m}`) : ""
                    }
                }
            }
        }
    }
    dangerZone = new Set(dangerZone)
    return zone - dangerZone.size
}

 
 
solution

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;
}

board 내 각 배열 내 요소를 돌며 해당 요소가 1이면 return false
outside 배열을 가져와 각 요소에 y축 index와 x축 index를 더해준다. 해당 좌표에 1이 하나라도 있으면 false를 반환하고 그렇지 않으면 safezone++를 해준다. 
즉, outside 배열은 상하좌우/대각선 위치의 좌표를 나타낸다.

728x90
반응형