robert-min / dev-blog

김민준 - project 정리한 repo입니다.
0 stars 0 forks source link

231116 - 블록게임(구현문제) #112

Open robert-min opened 1 year ago

robert-min commented 1 year ago

블록문제

dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]

def dfs(board, x, y, board_num, visited) :
    block = [(x, y, 1)]
    n = len(board)
    q = [(x, y)]
    visited[y][x] = True

    while q :
        x, y = q.pop()
        for i in range(4) :
            ax, ay = x + dx[i], y + dy[i]
            if -1 < ax < n and -1 < ay < n and board[ay][ax] == board_num and not visited[ay][ax] :
                block.append((ax, ay, 1))
                visited[ay][ax] = True
                q.append((ax, ay))

    return block

def min_rectangle(board, board_num, block) :
    x_list = sorted([ coord[0] for coord in block ])
    y_list = sorted([ coord[1] for coord in block ])

    for i in range(y_list[0], y_list[-1]+1) :
        for j in range(x_list[0], x_list[-1]+1) :
            if board[i][j] != board_num :
                block.append((j, i, 0))

def find_blocks(board):
    n = len(board)
    visited = [[False]*n for _ in range(n)]
    block_list = list()
    for i in range(n) :
        for j in range(n) :
            if not visited[i][j] and board[i][j] :
                # 2 블록 탐색
                block = dfs(board, j, i, board[i][j], visited)
                # 3 직사각형 좌표 탐색
                min_rectangle(board, board[i][j], block)
                block_list.append(block)

    return block_list

def is_block_enable(board, block) :
    for x, y, check in block :
        if check == 1 :
            continue
        for i in range(y, -1, -1) :
            if board[i][x] != 0 :
                return False
    return True

def check_all_blocks(board, block_list) :
    if not block_list :
        return 0, []

    n = len(board)
    block_num = len(block_list)
    new_block_list = list()
    cnt = 0

    for idx, block in enumerate(block_list) :
        # 5. 블럭이 지워지는지 확인
        if is_block_enable(board, block) :
            for x, y, _ in block :
                board[y][x] = 0
            cnt += 1
            continue
        new_block_list.append(block)

    return cnt, new_block_list

def solution(board):
    # 1. 모든 블록 탐색
    block_list = find_blocks(board)
    answer = 0
    while True :
        # 4. 모든 블록 탐색(앞에서 지워졌을 때 다른 블록이 지워질 수 있으니 cnt == 0 일때까지 반복
        cnt, block_list = check_all_blocks(board, block_list)
        answer += cnt
        if cnt == 0 :
            break

    return answer