알고리즘/프로그래머스

[프로그래머스 | Lv3] 퍼즐 조각 채우기 (Python)

sssbin 2023. 4. 11. 23:20

 

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

 

프로그래머스

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

programmers.co.kr

 

전체 로직

1. table -> 이어진 퍼즐 조각 부분만 잘라서 행렬로 만들어주고 board에 추가

2. game_board -> 이어진 빈 부분만 잘라서 행렬로 만들어주고 rotate하면서 각 수행문마다 board에 같은 값이 있는지 찾고 정답 추가

 

bfs(x, y, t, f, array, size)

- 큐에 [x, y]를 넣고 이어진 부분을 찾는다.

- table은 1을 찾아야 하고, game_board는 0을 찾아야 하기 때문에 변수 t를 뒀다.

- 이미 방문한 인덱스는 f값(table: 0, game_board: 1)으로 바꿔준다.

- 이어진 부분의 인덱스들을 저장한 배열을 반환한다.

 

make_board(array)

- 이어진 부분의 인덱스들의 최댓값, 최솟값을 찾아 행, 열의 크기를 구한다.

- 행x열의 크기의 배열을 선언하고 0으로 초기화한다.

- 입력받은 배열을 순회하면서 해당 부분만 1로 바꿔준다.

- 새로 만들어진 부분 배열을 반환한다.

 

rotate(array)

- 입력받은 배열을 90도 회전한 후 반환한다.

 

# 프로그래머스 84021: 퍼즐 조각 채우기

from collections import deque

def bfs(x, y, t, f, array, size):
    move = [[1, 0], [-1, 0], [0, 1], [0, -1]]
    temp = []
    queue = deque()
    queue.append([x, y])
    
    while queue:
        x, y = queue.popleft()
        array[x][y] = f
        temp.append([x, y])
        
        for dx, dy in move:
            mx = x + dx
            my = y + dy
            if mx < 0 or mx >= size or my < 0 or my >= size:
                continue
            if array[mx][my] == t:
                queue.append([mx, my])

    return temp

def make_board(array):
    x1 = min(array, key=lambda x:x[0])[0]
    x2 = max(array, key=lambda x:x[0])[0]
    y1 = min(array, key=lambda x:x[1])[1]
    y2 = max(array, key=lambda x:x[1])[1]
    sizeX = x2 - x1 + 1
    sizeY = y2 - y1 + 1
    
    temp = [[0] * sizeY for _ in range(sizeX)]
    for x, y in array:
        temp[x-x1][y-y1] = 1
        
    return temp

def rotate(array):
    r = [list(i) for i in zip(*array[::-1])]
    return r
    
    
def solution(game_board, table):
    size = len(game_board)
    board = [] # 퍼즐 조각들을 저장할 리스트
    
    for i in range(size):
        for j in range(size):
            if table[i][j] == 1:
                # table에서 이어진 퍼즐 조각을 찾고,
                temp = bfs(i, j, 1, 0, table, size)
                # 그 부분만 떼서 저장
                board.append(make_board(temp))
    
    visited = [False] * len(board) # table의 방문 여부를 체크할 리스트
    answer = 0
    check = 0 # break문을 위한 변수
    
    for i in range(size):
        for j in range(size):
            if game_board[i][j] == 0:
                # game_board에서 이어진 빈 부분을 찾고,
                temp = bfs(i, j, 0, 1, game_board, size)
                # 그 부분만 떼서 비교
                temp = make_board(temp)
                for k in range(4):
                    # 회전
                    temp = rotate(temp)
                    # board를 순회하면서
                    for b in range(len(board)):
                        if visited[b]:
                            continue
                        # 빈 부분과 board가 같으면 방문 처리 후 정답 추가
                        if temp == board[b]:
                            visited[b] = True
                            for t in temp:
                                answer += t.count(1)
                            check = 1
                            break
                    if check == 1:
                        check = 0
                        break
                    
    return answer

 

참,,,, 지저분하다,,,