[프로그래머스 LV2] 프렌즈 4블록

Junyoung Park·2022년 8월 20일
0

코딩테스트

목록 보기
577/631
post-thumbnail

1. 문제 설명

프렌즈 4블록

2. 문제 분석

현재 상태의 없앨 수 있는 블록을 얻어내는 함수, 얻어낸 블록을 중복 처리하는 방법, 블록 처리 후 빈 공간을 없애는 함수를 반복한다.

  1. 주어진 배열을 2차원 배열로 만든 뒤, 2X2의 정사각형 블록을 스캔한다.
  2. 주어진 정사각형이 모두 동일한 블록일 때(빈 블록이 아님) 매칭 성공
  3. 중복 블록을 카운팅하기 위해 집합 카운트
  4. 사라진 블록을 빈 칸으로, 매칭된 블록의 개수를 리턴
  5. 중간에 빈 칸이 있는 같은 '행'이라면 밑 단에서부터 스캔, 중간의 빈 블록을 무시하고 '존재하는' 블록만 카운트
  6. 각 노드의 행을 새롭게 구성함
  7. 블록 매칭을 통해 리턴되는 블록이 없을 때까지 반복

3. 나의 풀이

struct Position: Hashable {
    let row: Int
    let col: Int
}

func solution(_ m:Int, _ n:Int, _ board:[String]) -> Int {
    var nodes = makeNodes(board)
    
    func downBoxes() {
        var tmpRow = [String]()
        var tmpIndex = 0
        for i in 0..<n {
            tmpRow = []
            tmpIndex = 0
            for j in stride(from: m-1, to: -1, by: -1) {
                if nodes[j][i] != "" {
                    tmpRow.append(nodes[j][i])
                }
            }
            tmpRow += Array(repeating: "", count: m - tmpRow.count)
            for j in stride(from: m-1, to: -1, by: -1) {
                nodes[j][i] = tmpRow[tmpIndex]
                tmpIndex += 1
            }
        }
    }
    
    func matchBoxes() -> Int {
        var blockPositions = Set<Position>()
        for i in 0..<m-1 {
            for j in 0..<n-1 {
                let first = nodes[i][j]
                let second = nodes[i][j+1]
                let third = nodes[i+1][j]
                let fourth = nodes[i+1][j+1]
                if first == "" || second == "" || third == "" || fourth == "" {
                    continue
                }
                if first == second && second == third && third == fourth {
                    blockPositions.insert(Position(row: i, col: j))
                    blockPositions.insert(Position(row: i, col: j + 1))
                    blockPositions.insert(Position(row: i + 1, col: j))
                    blockPositions.insert(Position(row: i + 1, col: j + 1))
                }
            }
        }
        for position in blockPositions {
            let row = position.row
            let col = position.col
            nodes[row][col] = ""
        }
        
        return blockPositions.count
    }
    
    var total = 0
    
    while true {
        let blockCount = matchBoxes()
        if blockCount == 0 {
            break
        } else {
            total += blockCount
        }
        downBoxes()
    }
    print(total)
    return total
}

func makeNodes(_ board: [String]) -> [[String]] {
    var nodes = [[String]]()
    for row in board {
        let row = Array(row).map{String($0)}
        nodes.append(row)
    }
    return nodes
}
  • 블록을 스캔하는 곳, 블록을 재정렬하는 부분을 리팩토링한다면 보다 시간을 효율적으로 줄일 수 있을 것 같다.
profile
JUST DO IT

0개의 댓글