테이블 위에 놓인 퍼즐 조각을 게임 보드의 빈 공간에 적절히 올려놓으려 합니다. 게임 보드와 테이블은 모두 각 칸이 1x1 크기인 정사각 격자 모양입니다. 이때, 다음 규칙에 따라 테이블 위에 놓인 퍼즐 조각을 게임 보드의 빈칸에 채우면 됩니다.
다음은 퍼즐 조각을 채우는 예시입니다.
위 그림에서 왼쪽은 현재 게임 보드의 상태를, 오른쪽은 테이블 위에 놓인 퍼즐 조각들을 나타냅니다. 테이블 위에 놓인 퍼즐 조각들 또한 마찬가지로 [상,하,좌,우]로 인접해 붙어있는 경우는 없으며, 흰 칸은 퍼즐이 놓이지 않은 빈 공간을 나타냅니다. 모든 퍼즐 조각은 격자 칸에 딱 맞게 놓여있으며, 격자 칸을 벗어나거나, 걸쳐 있는 등 잘못 놓인 경우는 없습니다.
이때, 아래 그림과 같이 3,4,5번 조각을 격자 칸에 놓으면 규칙에 어긋나므로 불가능한 경우입니다.
다음은 규칙에 맞게 최대한 많은 조각을 게임 보드에 채워 넣은 모습입니다.
최대한 많은 조각을 채워 넣으면 총 14칸을 채울 수 있습니다.
현재 게임 보드의 상태 game_board, 테이블 위에 놓인 퍼즐 조각의 상태 table이 매개변수로 주어집니다. 규칙에 맞게 최대한 많은 퍼즐 조각을 채워 넣을 경우, 총 몇 칸을 채울 수 있는지 return 하도록 solution 함수를 완성해주세요.
- 로직 구현 설계를 정말 정말
제발...꼼꼼하게 해보도록 하자.
이 문제는 어떠한 알고리즘을 요구하기보다,
그냥 주어진 문제를 어떻게 해결하는 지 능력을 물어보는 거 같다.
키워드에서 요구했듯, 로직 구현을 정말 잘 해야 한다.
먼저, 나는 다음과 같은 과정을 진행해 구현하였다.
해당 문제를 이 과정으로 풀었지만, 반례가 존재하는 거 같다.
프로그래머스에서 정답이 뜨긴 했지만, 조금 더 세세하게 봐야할 거 같다.
이 문제를 풀 때, 몇 가지 주의사항이 있다.
예제로 다음과 같은 퍼즐조각이 있다고 가정하자.
BFS를 할 때, 12시 방향부터 시계방향으로 탐색한다고 가정할 때, 방향은 다음과 같이 저장된다.
노란색 퍼즐조각 : 우,우,하,우,우
초록색 퍼즐조각 : 우,우,하,우,우
이런 경우가 생기기 때문에, 가끔 조각이 맞지도 않는데 맞다고 뜨는 경우가 있을 것이다.
퍼즐조각을 뽑아낼 때, 방향을 저장한다면, 주의할 필요가 있다.
해당 문제에서 최소 row, col과 최대 row, col을 구하는 이유다.
문제의 테스트 케이스에서도 확인 할 수 있다.
해당 블록을 1번 블록과 비교한다고 하였을 때, 빈 칸에서 비교를 시작하면 이렇게 진행 될 것이다.
때문에, 빈 칸을 BFS로 탐색해 현재 찾은 빈칸에서 최대 row, col과 최소 row, col을 구해서
최소 row,col ~최대 row, col 까지 비교만 하면 된다.
# python
from collections import deque
d = [[-1,0],[0,1],[1,0],[0,-1]]
def spin(block):
spin_block = [[0]*len(block) for _ in range(len(block[0]))]
for row in range(len(block)):
for col in range(len(block[0])):
spin_block[col][len(spin_block[0])-1-row] = block[row][col]
return spin_block
def catch_piece(table,row,col):
R,C = len(table),len(table)
piece = [[0]*C for _ in range(R)]
piece[row][col] = 1
q = deque([[row,col]])
while q:
r,c = q.popleft()
piece[r][c] = 1
table[r][c] = 0
for i in d:
dr,dc = i
if 0 <= r+dr < R and 0 <= c+dc < C:
if table[r+dr][c+dc] == 1:
table[r+dr][c+dc] = 0
piece[r+dr][c+dc] = 1
q.append([r+dr,c+dc])
r_piece = []
for i in piece:
if sum(i) != 0:
r_piece.append(i)
r_piece = spin(r_piece)
c_piece = []
for i in r_piece:
if sum(i) != 0:
c_piece.append(i)
for _ in range(3):
c_piece = spin(c_piece)
return c_piece
def compare(game_board,piece,row,col):
R,C = len(game_board),len(game_board)
cnt = 0
for r in range(len(piece)):
for c in range(len(piece[0])):
if piece[r][c] == 1 and game_board[row+r][col+c] == 2:
cnt += 1
elif piece[r][c] == 0 and game_board[row+r][col+c] == 1:
continue
else:
return 0
return cnt
def solution(game_board,table):
answer = 0
piece = deque()
R,C = len(game_board),len(game_board)
for row in range(R):
for col in range(C):
if table[row][col] == 1:
piece.append(catch_piece(table,row,col))
for row in range(R):
for col in range(C):
if game_board[row][col] == 0:
q = deque([[row,col]])
min_row,max_row = row,row
min_col,max_col = col,col
while q:
r,c = q.popleft()
game_board[r][c] = 2
for i in d:
dr,dc = i
if 0 <= r+dr < R and 0 <= c+dc < C:
if game_board[r+dr][c+dc] == 0:
q.append([r+dr,c+dc])
min_row,max_row = min(min_row,r+dr),max(max_row,r+dr)
min_col,max_col = min(min_col,c+dc),max(max_col,c+dc)
game_board[r+dr][c+dc] = 2
result = 0
for p in range(len(piece)):
for _ in range(4):
if piece[p][0][0] == -1:
break
if len(piece[p]) == max_row-min_row+1 and len(piece[p][0]) == max_col-min_col+1:
result = compare(game_board,piece[p],min_row,min_col)
if result > 0:
answer += result
piece[p][0][0] = -1
break
piece[p] = spin(piece[p])
if result > 0:
break
return answer
if __name__ == "__main__":
print(solution([[0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0], [1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0], [1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1], [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0], [0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1], [0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0], [0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0], [1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0], [0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0], [0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1], [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0]],[[1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1], [1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0], [0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1], [1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1], [0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1], [1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1], [1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1], [1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1]])) # correct : 54
print(solution([[1,1,0,0,1,0],[0,0,1,0,1,0],[0,1,1,0,0,1],[1,1,0,1,1,1],[1,0,0,0,1,0],[0,1,1,1,0,0]],[[1,0,0,1,1,0],[1,0,1,0,1,0],[0,1,1,0,1,1],[0,0,1,0,0,0],[1,1,0,1,1,0],[0,1,0,0,0,0]]) # correct : 14
//java 작성 준비중
준비중
블록의 저장방식이 잘못되었을 때,
로직은 맞으나, 너무 과도하게 굴렸을 때,
현재,
난이도도 난이도지만 뭔가 너무 힘들었다.
딱히 알고리즘적으로 요구한 건 없었으나, 구현능력과 문제해결 능력부분에서 부족한 점이 많은 거 같다.
알고리즘 문제도 중요하지만, 구현능력 관련 문제를 많이 풀어서 문제해결 능력을 길러야 할 거 같다.
이걸 JAVA로 또 풀생각을 하려니 앞이 캄캄하다...
푸는데 얼마나 걸렷어용?