본문 바로가기
코딩 테스트/프로그래머스

[프로그래머스] (2018 카카오) 프렌즈4블록

by Dev.Andy 2023. 6. 7.

머리말

문제 링크

코딩테스트 연습 - [1차] 프렌즈4블록 | 프로그래머스 스쿨

이 문제를 선택한 이유

  • 구현 문제 연습

 

풀이

개요

우선 2개의 배열을 새로 만들었다.

  1. 반복문에 필요한 보드 배열(board 배열의 각 요소를 한 단어씩 구분하여 새로 할당) - boardArr
  2. 각 보드의 블록이 2*2 블록인지의 여부를 판단하는 배열 - isSquare

풀이 순서

  1. boardArr를 반복하면서 isSquare에 대한 참/거짓을 판별한다
  2. isSquare 중에 true인 부분의 인덱스에 위치한 boardArr의 요소를 공백으로 바꾸고 지워진 블록을 카운트한다 == 블록이 지워진다
  3. 공백이 바꾼 자리를 재배열한다 == 블록이 떨어진다

이제 1~3번을 계속 반복하는데, 공백이 한번도 되지 않을 때 반복을 중단하고 카운트한 블록을 반환한다

스위프트 코드

func solution(_ m:Int, _ n:Int, _ board:[String]) -> Int {
    
    var boardArr = board.map { Array($0) }
    var answer = 0
    
    // 제거한 블록이 없을 때까지 while loop 무한 반복
    while true {
        // 2*2 블록인지 판별할 배열의 요소를 false로 초기화
        var isSquare = Array(repeating: Array(repeating: false, count: n), count: m)
        
        // 2*2 블록일 경우 기본값 false를 true로 재할당
        for i in 0..<m-1 {
            for j in 0..<n-1 {
                var target = boardArr[i][j]
                if target != " " && target == boardArr[i][j+1]
                && target == boardArr[i+1][j] && target == boardArr[i+1][j+1] {
                    isSquare[i][j] = true
                    isSquare[i][j+1] = true
                    isSquare[i+1][j] = true
                    isSquare[i+1][j+1] = true
                }
            }
        }
        
        // 블록을 제거한 여부를 기본값으로 false로 할당
        var isRemovedBlock = false
        
        // 사각형인 부분을 공백으로 바꾸고, 제거한 여부를 true로 재할당, 결괏값을 1씩 증가
        for i in 0..<m {
            for j in 0..<n {
                if isSquare[i][j] == true {
                    boardArr[i][j] = " "
                    isRemovedBlock = true
                    answer += 1
                }
            }
        }
        
        // 제거한 블록이 없을 경우 while loop 탈출
        if !isRemovedBlock { break }
        
        // 제거한 블록이 아래로 떨어져 빈 공간 채우기
        for j in 0..<n {
            var emptyBlock = 0
            for i in (0..<m).reversed(){
                if boardArr[i][j] == " " { emptyBlock += 1 }
                else if emptyBlock > 0 {
                    boardArr[i + emptyBlock][j] = boardArr[i][j]
                    boardArr[i][j] = " "
                }
            }
        }
    }
    
    return answer
}

 

꼬리말

계속 이어지는 반복문

  • 이번에 푼 반복문은 3중 반복문이라서 큰 틀을 그려보는 게 쉽지 않았다.
  • "거듭 연습하는 수밖에 없지" 생각이 들었다.

블록이 떨어지는 걸 어떻게 구현하지…?

  • 기존에는 2차원 배열을 접근 할 때 항상 "가로 → 세로"의 순서로 접근했었다.
  • 하지만 이번에는 아래에 위치한 공백과 위에 위치한 기존 문자를 접근하려면 "세로 → 가로"의 순서를 접근해서 되게 어색했다.

공책으로 시도하는 손 코딩, 효과는 굉장했다

  • 노트와 펜으로 직접 예시를 적어 보고, 단계를 그려나가는 연습을 하니 훨씬 수월하게 풀 수 있었다.
  • 특히나 큰 틀로 구분하여 생각을 할 때는 직접 쓰는 게 도움이 많이 되었다.
  • 설명이 안되면 최대한 나의 언어로 이해가 될 때까지 연습을 해 보았다.
  • 앞으로도 손 코딩을 적극 활용해야지 ㅎㅎ

댓글