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

 

프로그래머스

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

programmers.co.kr



Solution

def friends(m, n, board, visited):
    for i in range(m-1):
        for j in range(1, n):
            if board[i][j] != ' ' and board[i][j] == board[i][j-1] and board[i][j-1:j+1] == board[i+1][j-1:j+1]:
                    visited[i][j] = True
                    visited[i][j-1] = True
                    visited[i+1][j] = True
                    visited[i+1][j-1] = True
    
def deleteBlock(m, n, board, visited):
    cnt = 0
    for i in range(m):
        for j in range(n):
            if visited[i][j] == True:
                cnt += 1
                board[i] = board[i][:j] + ' ' + board[i][j+1:]
    
    rotation_board = []
    for i in range(n):
        tmp = ''
        for j in range(m):
            tmp += board[j][i]
        rotation_board.append(tmp)
        
    for i in range(n):
        for j in range(1, m):
            if rotation_board[i][j] == ' ':
                rotation_board[i] = ' ' + rotation_board[i][:j] + rotation_board[i][j+1:]
    
    tmp_board = []
    for i in range(m):
        tmp = ''
        for j in range(n):
            tmp += rotation_board[j][i]
        tmp_board.append(tmp)
        
    board = tmp_board
    
    return board, cnt
    
def solution(m, n, board):
    answer = 0
    result = 1
    while result:
        visited = [[False] * n for _ in range(m)]
        friends(m, n, board, visited)
        board, result = deleteBlock(m, n, board, visited)
        answer += result
    return answer

 

블록을 나타내는 문자는 대문자 A-Z로, 라이언(R) / 무지(M) / 어피치(A) 등 문제에서 설명한 캐릭터들만 있는게 아니다. 즉 A부터 Z까지 각 문자가 나타내는 캐릭터가 있다고 생각하면 된다.

 

구현해야할 것

  • 카카오 프렌즈 블록에서 2X2 형태로 붙어있는 블록(제거할 블록)들을 찾는다.
  • 제거해야할 블록들을 없앤다.
  • 블록들을 없애고 위에 남아있는 블록들을 아래로 떨어트려 빈공간을 채운다.

나는 붙어있는 블록들을 찾는 함수와 블록을 제거하고 빈공간을 채우는 함수 2개를 만들었다. 2X2 형태의 블록을 찾는 것은 문자열을 비교하는 쪽으로 구현했다. 그렇게 2X2 형태를 띄고있으면 visited 배열에 True 값을 주고 deleteBlock 함수로 넘겨준다.

 

for i in range(m-1):
    for j in range(1, n):
        if board[i][j] != ' ' and board[i][j] == board[i][j-1] and board[i][j-1:j+1] == board[i+1][j-1:j+1]:
                visited[i][j] = True
                visited[i][j-1] = True
                visited[i+1][j] = True
                visited[i+1][j-1] = True

 

deleteBlock 함수에서는 처음에 받은 visited 배열에 True 값을 세고, 해당 블록을 제거해준다. 이제 문제는 블록들을 아래로 떨어트려 빈공간을 채우는 것이다. 위에서 아래로 떨어지는 것이기 때문에 비교해야할 열을 행으로 바꿔주었다. 배열 전체의 열을 행으로 바꿔주고, rotation_board 배열에 저장했다.

 

    rotation_board = []
    for i in range(n):
        tmp = ''
        for j in range(m):
            tmp += board[j][i]
        rotation_board.append(tmp)
        
    for i in range(n):
        for j in range(1, m):
            if rotation_board[i][j] == ' ':
                rotation_board[i] = ' ' + rotation_board[i][:j] + rotation_board[i][j+1:]

 

이렇게 바꿔주면 rotation_board 에서는 다른 걸 추가적으로 구현할 필요없이 처음 board의 블록을 제거할 때와 똑같은 방식으로 구현해주면 된다. rotation_board 에서 빈공간까지 다 채웠으면 tmp_board를 이용해서 board를 갱신한다.(지금 생각해보니 tmp_board를 생성할 필요가 없었다.

 

tmp_board = []
    for i in range(m):
        tmp = ''
        for j in range(n):
            tmp += rotation_board[j][i]
        tmp_board.append(tmp)

 


생강강

,