본문 바로가기
알고리즘

[Swift] 프로그래머스 - 카카오 기둥과 보 설치

by 고고 2022. 6. 27.

링크: https://programmers.co.kr/learn/courses/30/lessons/60061

 

코딩테스트 연습 - 기둥과 보 설치

5 [[1,0,0,1],[1,1,1,1],[2,1,0,1],[2,2,1,1],[5,0,0,1],[5,1,0,1],[4,2,1,1],[3,2,1,1]] [[1,0,0],[1,1,1],[2,1,0],[2,2,1],[3,2,1],[4,2,1],[5,0,0],[5,1,0]] 5 [[0,0,0,1],[2,0,0,1],[4,0,0,1],[0,1,1,1],[1,1,1,1],[2,1,1,1],[3,1,1,1],[2,0,0,0],[1,1,1,0],[2,2,0,1]] [[

programmers.co.kr

 

 

1. _isRightPillar, _isRightBo, _isRightAll 함수를 만듭니다.

2. 설치 시에는 _isRightPillar 또는 _isRightBo 함수를 사용합니다. 올바른 기둥 또는 보라면 result에 추가합니다.

3. 삭제 시에는 _isRightAll 함수를 통해 임시로 기둥 또는 보를 삭제 후의 모든 기둥과 보가 올바른지 검사합니다. 올바르지 않다면 임시로 삭제한 것을 되돌리고, 올바르다면 그대로 삭제합니다.

4. 결과를 정렬합니다.

import Foundation

func solution(_ n:Int, _ build_frame:[[Int]]) -> [[Int]] {
    var result = [[Int]]() // [x, y, 0 or 1] 기둥 0 보 1
    
    func _isRightPillar(_ x: Int, _ y: Int) -> Bool {
        // 기둥은 바닥 위에 있거나 보의 한쪽 끝 부분 위에 있거나, 또는 다른 기둥 위에 있어야 합니다.
        if y == 0 {
           return true
        } else {
            for r in result {
                if r[2] == 0 { // 기둥
                    if r[0] == x && r[1] == y - 1 {
                        return true
                    }
                } else { // 보
                    if (r[0] == x && r[1] == y) || (r[0] == x - 1 && r[1] == y) {
                        return true
                    }
                }
            }
        }
        
        return false
    }
    
    func installPillar(_ x: Int, _ y: Int) {
        if _isRightPillar(x, y) {
            result.append([x, y, 0])
            return
        }
    }
    
    func _isRightBo(_ x: Int, _ y: Int) -> Bool {
        // 보는 한쪽 끝 부분이 기둥 위에 있거나, 또는 양쪽 끝 부분이 다른 보와 동시에 연결되어 있어야 합니다.
        var sideBoCount = 0
        
        for r in result {
            if r[2] == 0 { // 기둥
                if r[0] == x && r[1] == y - 1 {
                    return true
                } else if r[0] == x + 1 && r[1] == y - 1 {
                    return true
                }
            } else { // 보
                if (r[0] == x - 1 && r[1] == y) || (r[0] == x + 1 && r[1] == y) {
                    sideBoCount += 1
                }
                
                if sideBoCount == 2 {
                    return true
                }
            }
        }
        
        return false
    }
    
    func installBo(_ x: Int, _ y: Int) {
        if _isRightBo(x, y) {
            result.append([x, y, 1])
            return
        }
    }
    
    func _isRightAll() -> Bool {
        for r in result {
            if r[2] == 0 { // 기둥
                if !_isRightPillar(r[0], r[1]) {
                    return false
                }
            } else {
                if !_isRightBo(r[0], r[1]) {
                    return false
                }
            }
        }
        
        return true
    }
    
    func delete(_ x: Int, _ y: Int, _ isBo: Int) {
        let temp = result
        result = result.filter { $0 != [x, y, isBo] }
        
        if !_isRightAll() {
           result = temp // 되돌려놓기
        }
    }
    
    for frame in build_frame {
        let x = frame[0]
        let y = frame[1]
        let isBo = frame[2]
        let isInstall = frame[3]
        
        if isInstall == 1 { // 설치
            if isBo == 0 {
                installPillar(x, y)
            } else {
                installBo(x, y)
            }
        } else { // 삭제
            delete(x, y, isBo)
        }
    }
    
    // return 하는 배열은 x좌표 기준으로 오름차순 정렬하며, x좌표가 같을 경우 y좌표 기준으로 오름차순 정렬해주세요.
    // x, y좌표가 모두 같은 경우 기둥이 보보다 앞에 오면 됩니다.
    return result.sorted(by: {
        if $0[0] == $1[0] {
            if $0[1] == $1[1] {
                return $0[2] < $1[2]
            } else {
                return $0[1] < $1[1]
            }
        } else {
            return $0[0] < $1[0]
        }
    })
}

댓글