Swift) 2018 KAKAO BLIND RECRUITMENT - 프렌즈 4블록

https://school.programmers.co.kr/learn/courses/30/lessons/17679

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

구현 + 시뮬레이션 문제

 

같은 모양의 블록이 2 * 2 이상 짝수로 붙어 있을 시 그 블록들을 지우고, 위에 있는 블록이 아래로 내려온다. 

 

풀이 방식: 보드를 가로 n-1, 세로 n-1을 반복해서 탐색한다. 탐색하는 블록의 x+1, y+1, (x+1, y+1)이 같은 모양인지 체크하고 모두 같은 모양일 시  removeLocation에 해당 블록의 위치를 저장한다. 탐색을 모두 마쳤다면 removeLocation의 위치를 기준으로 보드의 (x,y), (x+1, y), (x,y+1), (x+1, y+1)을 0으로 만듭니다.

 

이번에는 블록을 아래로 내릴 차례입니다. 이번에는 보드의 y축 n-1부터 탐색을 합니다. 탐색하는 보드의 y+1이 0이 아닐때 까지 보드의 (x,y+1)에 (x,y)의 값을 넣고, (x,y)에 0을 넣습니다.

 

만약 탐색을 마쳤는데, 지울 블록이 없다면 반복을 종료합니다.

 

let dx = [1,0,1]
let dy = [0,1,1]

func solution(_ m:Int, _ n:Int, _ board:[String]) -> Int {
    var boardArr: [[Character]] = board.map{Array($0)}
    var answer = 0
    func removeBlock(_ y: Int, _ x: Int) {
        boardArr[y][x] = "0"
        for i in 0..<3 {
            boardArr[y+dy[i]][x+dx[i]] = "0"
        }
    }
    
    func downBlock() {
        for i in (0..<m-1).reversed() {
            for j in (0..<n).reversed() {
                if boardArr[i][j] == "0" {
                    continue
                }
                var currentY = i
                while true {
                    if currentY >= m-1 {
                        break
                    }
                    if boardArr[currentY+1][j] == "0" {
                        boardArr[currentY+1][j] = boardArr[currentY][j]
                        boardArr[currentY][j] = "0"
                    } else {
                        break
                    }
                    currentY += 1
                }
            }
        }
    }
    
    func checkIsBlock(_ y: Int, _ x: Int) -> Bool {
        let currentCharacter = boardArr[y][x]
        for i in 0..<3 {
            if boardArr[y+dy[i]][x+dx[i]] != currentCharacter {
                return false
            }
        }
        return true
    }
    
    while true {
        var flag = false
        var removeLocation: [(Int, Int)] = []
        for i in 0..<m-1 {
            for j in 0..<n-1 {
                if boardArr[i][j] == "0" {
                    continue
                }
                if checkIsBlock(i,j) {
                    flag = true
                    removeLocation.append((i,j))
                }
            }
        }
        
        if !flag {
            break
        }
    
        for removeCoordi in removeLocation {
            removeBlock(removeCoordi.0, removeCoordi.1)
        }
        downBlock()
    }
    for i in boardArr {
        answer += i.filter { $0 == "0" }.count
    }
    return answer
}