์ž๋ฃŒ๊ตฌ์กฐ & ์•Œ๊ณ ๋ฆฌ์ฆ˜

[ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค] ํ”„๋ Œ์ฆˆ4๋ธ”๋ก

๊ธฐ๊ฐ€์ •ํ›ˆ 2023. 6. 25. 22:54

 

์ด ๋ฌธ์ œ๋Š” ์ตœ๊ทผ์— ๋„ค์ด๋ฒ„ ๋ถ€์ŠคํŠธ ์บ ํ”„ 2์ฐจ ์ฝ”๋”ฉ ํ…Œ์ŠคํŠธ๋ฅผ ์ค€๋น„ํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌํ˜„ ๋ฌธ์ œ๋ฅผ ์ฐพ์•„๋ณด๋˜ ์ค‘ ํ•˜๋‚˜์ธ "ํ”„๋ Œ์ฆˆ 4๋ธ”๋ก" ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ณด๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. 1์ฐจ ํ•ฉ๊ฒฉ ๋ฉ”์ผ์„ ๋ฐ›์•˜์„ ๋•Œ ๋‹น์‹œ์— 2๋ฐ• 3์ผ ๋™์•ˆ ๋™์› ํ›ˆ๋ จ ์ค‘์ด์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ํœด๋Œ€ํฐ์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ’€๊ธฐ ์œ„ํ•ด ๋ฉ”๋ชจ์žฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ์Šˆ๋„์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์ƒ๊ฐ์„ ์ •๋ฆฌํ•ด ๋‘” ๋ฌธ์ œ์˜€์Šต๋‹ˆ๋‹ค.

 

์ด๋ฒˆ ์ฝ”๋“œ๋Š” ํ•˜๋‚˜์”ฉ ์„ค๋ช…ํ•˜๋ฉด ๋„ˆ๋ฌด ๊ธธ์–ด์ง€๊ณ  ๊ฐ€๋…์„ฑ์ด ์ข‹์ง€ ์•Š์„ ๊ฑฐ ๊ฐ™์•„ ์ตœ๋Œ€ํ•œ ์ฝ”๋“œ ์•ˆ์— ์ฝ”๋“œ์˜ ์—ญํ• ์„ ์ ์–ด๋ณด๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.


1. ๋ฌธ์ œ ๋งํฌ 

 

 

ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค

์ฝ”๋“œ ์ค‘์‹ฌ์˜ ๊ฐœ๋ฐœ์ž ์ฑ„์šฉ. ์Šคํƒ ๊ธฐ๋ฐ˜์˜ ํฌ์ง€์…˜ ๋งค์นญ. ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค์˜ ๊ฐœ๋ฐœ์ž ๋งž์ถคํ˜• ํ”„๋กœํ•„์„ ๋“ฑ๋กํ•˜๊ณ , ๋‚˜์™€ ๊ธฐ์ˆ  ๊ถํ•ฉ์ด ์ž˜ ๋งž๋Š” ๊ธฐ์—…๋“ค์„ ๋งค์นญ ๋ฐ›์œผ์„ธ์š”.

programmers.co.kr

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

 

2. ์ฝ”๋“œ

func solution(_ m:Int, _ n:Int, _ board:[String]) -> Int {
    
    struct Tuple: Hashable{     //๋ธ”๋ก์„ ์ง€์šฐ๊ธฐ ์œ„ํ•ด ์œ„์น˜ ๊ฐ’
        let x : Int
        let y : Int
    }
    
    var lineUp : [[String]] = []   // ๋“ค์–ด์˜ค๋Š” ๊ฐ’์„ 2์ฐจ์› ๋ฐฐ์—ด ๋ณด๋“œํŒ์œผ๋กœ ๋งŒ๋“ฌ
    var blockIndex = Set<Tuple>()  // ์ œ๊ฑฐํ•ด์•ผํ•˜๋Š” ๋ธ”๋ก ์œ„์น˜ ์ค‘๋ณต ์•ˆ๋˜๊ฒŒ ์ €์žฅ
    var possible : Bool = true      // 4๋ฌถ์Œ ๋ธ”๋ก์ด ์กด์žฌํ•œ๋‹ค๋ฉด ํ”„๋กœ์„ธ์Šค ์ง„ํ–‰
    var result : Int = 0            // ๊ฒฐ๊ณผ๊ฐ’ ์ถœ๋ ฅ
    
    // MARK: lineUP ๊ตฌ์„ฑ
    /// 2์ฐจ์› ๋ฐฐ์—ด์œผ๋กœ ๋ณด๋“œํŒ ๊ตฌ์„ฑ
    for j in Array(board){
        var temp : [String] = []
        for k in j{
            temp.append(String(k))
        }
        lineUp.append(temp)
    }
    
    // MARK: 4๋ฌถ์Œ ๋ธ”๋ก ์ฐพ๊ธฐ
    func findBlockIndex(){
        for i in 0..<lineUp.count{
            for j in 0..<lineUp[i].count{
                if lineUp[i][j] == "0"{     // 0์€ ๋นˆ์นธ์ด๋ฏ€๋กœ checkingํ•  ํ•„์š” ์—†์ด ํŒจ์Šค
                    continue
                }
                checking(x: i, y: j, element: lineUp[i][j]) // ๋ณด๋“œํŒ ํ•˜๋‚˜์”ฉ ์ „๋ถ€ ํƒ์ƒ‰
            }
        }
        
        // blockIndex.isEmpty๊ฐ€ ๋น„์–ด์žˆ๋‹ค๋Š” ๋œป์€ ์ด์   ๋” ์ด์ƒ 4๋ฌถ์Œ ์š”์†Œ๊ฐ€ ์—†์–ด while๋ฌธ์„ ์ข…๋ฃŒํ•ด๋„ ๋จ
        if blockIndex.isEmpty{
            possible = false    // while ๋„๊ธฐ
        }
    }
    // MARK: 4๋ฌถ์Œ ํ™•์ธ
    /// ์ง„ํ–‰ํ•˜๊ณ  ์žˆ๋Š” ์œ„์น˜์—์„œ ์˜ค๋ฅธ์ชฝ,์•„๋ž˜, ๋Œ€๊ฐ์„  ๊ฐ’์ด ๊ฐ™์€ ์š”์†Œ์ธ์ง€ ํ™•์ธ
    func checking(x: Int, y: Int, element: String) {
        let dx = [0,1,1]
        let dy = [1,0,1]

        for i in 0..<3{     //3๋ฒˆ์„ ํ†ตํ•ด ์˜ค๋ฅธ์ชฝ,์•„๋ž˜,๋Œ€๊ฐ์„  ํƒ์ƒ‰
            if isValid(x: x+dx[i], y: y+dy[i]){
                // ํƒ์ƒ‰ํ•˜๋Š” ์œ„์น˜ ๊ฐ’์˜ ์š”์†Œ๊ฐ€ ์ „๋‹ฌ๋ฐ›์€ element์ด๋ž‘ ๋‹ค๋ฅผ์‹œ return
                if lineUp[x+dx[i]][y+dy[i]] != element{
                    return
                }
            }else{      //๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚˜๋„ return
                return
            }
        }
        
        possible = true //while๋ฌธ ๋ฐ˜๋ณตํ•˜๊ธฐ ์œ„ํ•ด true
        blockIndex.insert(Tuple(x: x, y: y))    //์ „๋‹ฌ ๋ฐ›์€ x,y๊ฐ’ ์ œ๊ฑฐ๋ฅผ ํ•  blockIndex์— ์ €์žฅ
        for i in 0..<3{
            if isValid(x: x+dx[i], y: y+dy[i]){
                blockIndex.insert(Tuple(x: x+dx[i], y: y+dy[i]))    // ํƒ์ƒ‰ํ•œ ๊ฐ’๋„ ์ €์žฅ
            }
        }
        return  //๋‹ค์Œ ์ˆœ์„œ๋กœ ์ง„ํ–‰์„ ์œ„ํ•ด
    }
    
    // MARK: ๋ฐฐ์—ด ๋ฒ”์œ„ ํ™•์ธ
    func isValid(x: Int, y: Int) -> Bool{
        // ๋ฒ”์œ„์•ˆ์— ์žˆ๋‹ค๋ฉด true, ์•„๋‹์‹œ false
        if x < m && y < n {
            return true
        }
        return false
    }
    // MARK: 4๋ฌถ์Œ ์š”์†Œ ์ง€์šฐ๊ธฐ
    func removeBlock(){
        // ์ €์žฅํ•ด๋‘” ๋ธ”๋ก ์ธ๋ฑ์Šค ๊ฐ’์„
        for i in blockIndex{
            lineUp[i.x][i.y] = "0"      //์ง€์›Œ์•ผ ํ•˜๋Š” ๋ธ”๋ก ๊ฐ’ "0"์œผ๋กœ ๋ฐ”๊พธ๊ธฐ
        }
        result += blockIndex.count      //๋งคํŒ๋งˆ๋‹ค ์ง€์šด ๋ธ”๋ก ์ˆ˜ result์— ์ €์žฅ
        blockIndex = []     //๋งคํŒ๋งˆ๋‹ค ํŒ๋‹จํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ดˆ๊ธฐํ™”
    }
    // MARK: ๋ณด๋“œํŒ ๋‹ค์‹œ ๋งŒ๋“ค๊ธฐ
    func rebuildingBlock(){
        // ๋ณด๋“œํŒ ๋ฐฐ์—ด์˜ ์ธ๋ฑ์Šค๋ฅผ ๊ฑฐ๊ฟ€๋กœ ์กฐํšŒํ•˜์—ฌ ๋น„์–ด์žˆ๋Š” ๋ถ€๋ถ„ ๋ฐ‘์œผ๋กœ ๋‚ด๋ฆฌ๊ธฐ
        for i in stride(from: lineUp.count-1, through: 0, by: -1){
            for j in  stride(from: lineUp[i].count-1, through: 0, by: -1){
                if lineUp[i][j] != "0"{     // ํ™•์ธํ•˜๊ณ  ์žˆ๋Š” ์š”์†Œ์˜ ๊ฐ’์ด 0์ด ์•„๋‹ˆ๋ผ๋ฉด ํ™•์ธํ•˜๊ธฐ
                    movingDownBlock(x: i, y: j)
                }
            }
        }
       
    }
    // MARK: ๋ธ”๋ก ์•„๋ž˜๋กœ ๋‚ด๋ฆฌ๊ธฐ
    func movingDownBlock(x: Int, y:Int){
        // ์•„๋ž˜๋กœ ๋‚ด๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— x+1 ๋ฒ”์œ„๊ฐ€ ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธ
        if isValid(x: x+1, y: y){
            if lineUp[x+1][y] == "0"{   // ๋ฐ‘์— ์žˆ๋Š” ์นธ์ด "0" -> ๋น„์–ด์žˆ๋ฏ€๋กœ
                lineUp[x+1][y] = lineUp[x][y]   //๋ฐ‘์— ์นธ์— ์ง€๊ธˆ lineUp[x][y] ๊ฐ’ ๋„ฃ๊ธฐ
                lineUp[x][y] = "0"              //lineUp[x][y] ๊ฐ’์„ ๋นˆ์นธ์œผ๋กœ ๋ฐ”๊พธ๊ธฐ
                movingDownBlock(x: x+1, y: y)   // ์žฌ๊ท€๋ฅผ ํ†ตํ•ด ๋” ๋ฐ‘์œผ๋กœ ๋‚ด๋ ค๊ฐˆ ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธ
            }
        }
        
    }
    
    // ๋ฐ˜๋ณต์„ ํ†ตํ•ด 1. 4๋ฌถ์Œ ์ฐพ์•„ ์œ„์น˜ ์ธ๋ฑ์Šค ์ €์žฅ 2. ์ €์žฅํ•ด๋‘” ์œ„์น˜๊ฐ’ ๋ธ”๋ก ์ง€์šฐ๊ธฐ 3. ๋ธ”๋ก ์žฌ์ •๋น„ -> 4๋ฌถ์Œ ์—†์„ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต
    while possible{
        findBlockIndex()
        removeBlock()
        rebuildingBlock()
    }
    
    return result
}

 

3.  ์ฝ”๋“œ ์„ค๋ช…

์ฒ˜์Œ์—๋Š” 4๊ฐœ์˜ ๋ธ”๋ก์„ ์–ด๋–ป๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ์„๊นŒ ๊ณ ๋ฏผํ–ˆ๋Š”๋ฐ, ๋ณด๋“œ๋ฅผ 2์ฐจ์› ๋ฐฐ์—ด๋กœ ๋งŒ๋“ค์–ด ๊ธธ ์ฐพ๊ธฐ์™€ ์œ ์‚ฌํ•œ ๋ฐฉ์‹์œผ๋กœ ์ ‘๊ทผํ•˜์—ฌ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค. ์ค‘๋ณต๋œ ๊ฐ’์€ Set์„ ์ด์šฉํ•˜์—ฌ ์ œ์™ธํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๋‹ค์Œ์œผ๋กœ๋Š” ๋ธ”๋ก์„ ์ œ๊ฑฐํ•˜๊ณ  ์•„๋ž˜๋กœ ๋‚ด๋ฆฌ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๊ณ ๋ฏผํ–ˆ์Šต๋‹ˆ๋‹ค. 2์ฐจ์› ๋ฐฐ์—ด์˜ ๋ธ”๋ก์€ ๋Œ€๋ถ€๋ถ„ ์ฑ„์›Œ์ ธ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋’ค์—์„œ๋ถ€ํ„ฐ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒƒ์ด ๋” ํšจ์œจ์ ์ผ ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ x ๊ฐ’๋งŒ ๊ณ ์ •๋œ ์ƒํƒœ์—์„œ -1์”ฉ ๋‚ด๋ ธ์Šต๋‹ˆ๋‹ค.

 

๋งˆ์ง€๋ง‰์œผ๋กœ๋Š” 4๊ฐœ์˜ ๋ธ”๋ก์ด ์žˆ๋Š” ๋™์•ˆ์—๋งŒ ๊ณ„์† ์ง„ํ–‰ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ๊ฐ ํŒ์ด ๋๋‚  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๋ณด๋“œํŒ์ด ์ƒ๊ธฐ๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ป๊ฒŒ ๋๊นŒ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์„๊นŒ ๊ณ ๋ฏผํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์—์„œ blockIndex.isEmpty๋ฅผ ์ด์šฉํ•˜์—ฌ while๋ฌธ์˜ ์กฐ๊ฑด์„ ์ปจํŠธ๋กคํ–ˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋ฒˆ์—๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉฐ ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค๊ณ  ๋ฐ˜ํ™˜๊ฐ’์„ ๊ณ ๋ คํ•˜๋ฉฐ ๋‹จ๊ณ„์ ์œผ๋กœ ๋‚˜๋ˆ„์–ด์„œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์—์„œ ์ฝ”๋“œ๋ฅผ ์กฐ๋ฆฝํ•˜๋Š” ๋Š๋‚Œ์ด ๋“ค์—ˆ๊ณ , ๊ฐ€๋…์„ฑ์ด ์ข‹์•„์ง„ ๊ฒƒ ๊ฐ™์•„ ๋ ˆ๊ณ ์ฒ˜๋Ÿผ ์กฐ๋ฆฝํ•˜๋Š” ๋Š๋‚Œ์ด์—ˆ์Šต๋‹ˆ๋‹ค.