[프로그래머스] 안전지대

Sdoubleu·2023년 7월 4일
0

프로그래머스

목록 보기
32/34
post-thumbnail

문제


내가 쓴 풀이

class Solution {
    fun solution(board: Array<IntArray>): Int {
        
        var answer: Int = 0
        
        val mut = Array(board.size) { row -> board[row].copyOf() }
        
        for (i in 0 until board.size) {
            for (j in 0 until board[i].size) {
                if(board[i][j] == 1){
                // 하단
                if(i + 1 >= 0 && i + 1 < board.size){
                    if(j - 1 >= 0 && j - 1 < board[i].size) mut[i+1][j-1] = 1
                    if(j >= 0 && j < board[i].size) mut[i+1][j] = 1
                    if(j + 1 >= 0 && j + 1 < board[i].size) mut[i+1][j+1] = 1
                }

                // 중단
                if(i >= 0 && i < board.size){
                    if(j - 1 >= 0 && j - 1 < board[i].size) mut[i][j-1] = 1
                    if(j + 1 >= 0 && j + 1 < board[i].size) mut[i][j+1] = 1
                }

                // 상단
                if(i - 1 >= 0 && i - 1 < board.size){
                    if(j - 1 >= 0 && j - 1 < board[i].size) mut[i-1][j-1] = 1
                    if(j >= 0 && j < board[i].size) mut[i-1][j] = 1
                    if(j + 1 >= 0 && j + 1 < board[i].size) mut[i-1][j+1] = 1
                    }
                }
            }
        }
        
        for(i in mut){ 
            for(j in i) if(j == 1) answer++
        }
        
        return board.size * board[0].size - answer
    }
}

원본과 복사본을 이용해서 원본을 for문을 돌려서 원소를 비교하여
복사본에 값을 변경해줌으로써 안전지대를 변경할 생각이였지만

처음엔 단순히 값을 대입만 하면 된다고 생각했지만 대입을 하게 되면
얕은 복사가 수행되므로 동일한 객체를 가르키게되어
복사본인 mut를 변경 시키면 원본도 변경되어 인덱스 범위를 벗어나게 된다

그러므로 깊은 복사를 수행하여 원본과 복사본을 분리시켜
원본의 원소만으로 값을 비교하여 복사본의 원소를 변경시켜준다

  • val mut = Array(board.size) { row -> board[row].copyOf() }
    -> board 배열의 크기와 동일한 크기의 새로운 2차원 배열을 생성한다 그리고
    각 행에 대해 board[row].copyOf()를 호출하여 해당 행의 요소를 새로운 배열에 복사한다

  • 2중 포문
    -> 원본의 원소가 1일 경우 인덱스를 벗어나지 않는 범위내에서만 바꿔준다

  • 비무장지대인 곳을 찾아서 count 해준다


다른 사람 풀이

class Solution {
    fun solution(board: Array<IntArray>): Int =
    board.indices.map { row ->
        board[row].indices.filter { board[row][it] == 1 }.forEach { col ->
            ((row - 1).coerceAtLeast(0)..(row + 1).coerceAtMost(board.lastIndex)).map { row2 ->
                ((col - 1).coerceAtLeast(0)..(col + 1).coerceAtMost(board.first().lastIndex)).forEach { col2 ->
                    if (board[row2][col2] == 0)
                        board[row2][col2] = 2
                }
            }
        }
    }.run { board.indices.map { board[it].count { value -> value == 0 } } }.sum()
}

해석

class Solution {
    fun solution(board: Array<IntArray>): Int =
        // 각 행 인덱스에 대해 반복
        board.indices.map { row ->
            // 현재 행에서 값이 1인 열 인덱스를 필터링하여 반복
            board[row].indices.filter { board[row][it] == 1 }.forEach { col ->
                // 현재 위치를 중심으로 주변 8개의 위치에 대해 반복
                // 행 인덱스 범위: (row - 1)..(row + 1)
                ((row - 1).coerceAtLeast(0)..(row + 1).coerceAtMost(board.lastIndex)).map { row2 ->
                    // 열 인덱스 범위: (col - 1)..(col + 1)
                    ((col - 1).coerceAtLeast(0)..(col + 1).coerceAtMost(board.first().lastIndex)).forEach { col2 ->
                        // 주변 위치가 0인 경우 2로 변경
                        if (board[row2][col2] == 0)
                            board[row2][col2] = 2
                    }
                }
            }
        }
        // 각 행에서 0의 개수를 세어 리스트로 변환
        .run { board.indices.map { board[it].count { value -> value == 0 } } }
        // 0의 개수 리스트의 합을 반환
        .sum()
}

📌참고자료

CoerceIn, coerceAtMost, coerceAtLeast 범위지정 함수에 대한

profile
개발자희망자

0개의 댓글