๐ฑ ๋ฌธ์
BFS/DFS ๋ฌธ์ ์ด์ง๋ง ๊ฐ์ธ์ ์ผ๋ก BFS ์ฐ๋ ์ฐ๊ณ , ์์ ๋นก์ ๊ตฌํ์ธ ๊ฒ ๊ฐ์๋.. ๋ฌธ์ ์ ๋๋ค.
๐ฑ ํ์ด
1. game_board์ ๋น ๊ณต๊ฐ๊ณผ table์ ํผ์ฆ ์ ๋ณด๋ฅผ ์ ์ฅ
์ฐ์ , game_board
์์ ๋น๊ณต๊ฐ๊ณผ table
์์ ํผ์ฆ๋ค์ ์ ๋ณด๋ฅผ ์์์ผ ํฉ๋๋ค. ์ฆ, game_board
์์๋ 0์ ์์น, table
์์๋ 1์ ์์น๋ฅผ ์์์ผํฉ๋๋ค. game_board
์ ์ธ์ ํ 0๋ค์ ํ๋์ ํผ์ฆ์ด ๋ค์ด๊ฐ ์ ์๋ ํ๋์ ๋น๊ณต๊ฐ์ผ๋ก ์ทจ๊ธํ๊ณ , table
์์ ์ธ์ ํ 1์ ํ๋์ ํผ์ฆ์ด๋ฏ๋ก BFS ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ์ฌ ์ ๋ณด๋ฅผ ์ ์ฅํฉ๋๋ค.
๊ฐ์ BFS ์๊ณ ๋ฆฌ์ฆ์ game_board
์ table
๋ก ๋ ๋ฒ ์จ์ผ ํ๊ธฐ ๋๋ฌธ์ ํจ์ํ ํ์๊ณ , ์ด๋ game_board
์์๋ 0์ ์์น๋ฅผ table
์์๋ 1์ ์์น๋ฅผ ์์์ผ ํ๋ฏ๋ก find_block()
ํจ์์์ f
์ธ์๋ฅผ ๋ฐ์ XOR(^
) ์ฐ์ฌ์์ ํจ๊ป ํจ์ ๋ด๋ถ์์ 0์ 1๋ก ๋ณํํ์ฌ ์๋ง๊ฒ ์ฌ์ฉํ์์ต๋๋ค.
from collections import deque
dx = [0, 0, -1, 1]
dy = [-1, 1, 0, 0]
def find_block(board, f):
empty_board_list = []
visited = [[False] * len(board[0]) for _ in range(len(board))]
for i in range(len(board)):
for j in range(len(board[i])):
if not visited[i][j] and board[i][j] == f:
queue = deque([(i, j)])
board[i][j] = f ^ 1
visited[i][j] = True
lst = [(i, j)]
while queue:
x, y = queue.popleft()
for _ in range(4):
nx, ny = x + dx[_], y + dy[_]
if nx < 0 or nx > len(board) - 1 or ny < 0 or ny > len(board) - 1:
continue
elif board[nx][ny] == f:
queue.append((nx, ny))
board[nx][ny] = f ^ 1
visited[nx][ny] = True
lst.append((nx, ny))
empty_board_list.append(lst)
return empty_board_list
์๋์ game_board
์ table
์ ๋ณด๋ฅผ find_block()
ํจ์์ ๋ฃ์ผ๋ฉด ์๋์ ๊ฐ์ด ๋ธ๋ก๋ค์ ์ ๋ณด๊ฐ ๋ด๊น๋๋ค.
game_board = [
[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]
]
table = [
[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]
]
empty_blocks = find_block(game_board, 0)
# [[(0, 2), (0, 3), (1, 3), (2, 3), (2, 4)], [(0, 5), (1, 5)], [(1, 0), (1, 1), (2, 0)], [(3, 2), (4, 2), (4, 1), (4, 3)], [(4, 5), (5, 5), (5, 4)], [(5, 0)]]
puzzles = find_block(table, 1)
# [[(0, 0), (1, 0)], [(0, 3), (0, 4), (1, 4), (2, 4), (2, 5)], [(1, 2), (2, 2), (2, 1), (3, 2)], [(4, 0), (4, 1), (5, 1)], [(4, 3), (4, 4)]]
2. ์ธ๋ฑ์ค ์ ๋ณด๋ก 2์ฐจ์ ๋ฆฌ์คํธ ๋ง๋ค๊ธฐ
์ธ๋ฑ์ค ์ ๋ณด๋ก table ๋ชจ์, ์ฆ 2์ฐจ์ ๋ฆฌ์คํธ ํํ๋ก ๋ง๋ค ์ฐจ๋ก์
๋๋ค. ์๋ฅผ ๋ค๋ฉด, ์๋์ ๊ฐ์ด ์์ find_blocks()
ํจ์์์ ์ฐพ์ [(0, 2), (0, 3), (1, 3), (2, 3), (2, 4)] ์ ๋ณด๋ฅผ ์๋์ ๊ฐ์ 2์ฐจ์ ๋ฆฌ์คํธ ํํ๋ก ๋ง๋๋ ๊ฒ์
๋๋ค.
์ ๋ make_table()
๋ผ๋ ํจ์๋ก ๋ง๋ค์ด์ฃผ์๊ณ ์ฝ๋๋ ์๋์ ๊ฐ์ต๋๋ค.
def make_table(block):
x, y = zip(*block)
c, r = max(x) - min(x) + 1, max(y) - min(y) + 1
table = [[0] * r for _ in range(c)]
for i, j in block:
i, j = i - min(x), j - min(y)
table[i][j] = 1
return table
3. 2์ฐจ์ ๋ฆฌ์คํธ๋ฅผ ํ์ ํ๋ ํจ์
์ด ๋ฌธ์ ์์ ์ค์ํ ํจ์์
๋๋ค. ํผ์ฆ์ 90๋์ฉ ํ์ ํ๋ฉด์ ๋น์นธ์ ์ฑ์ธ ์ ์๊ธฐ ๋๋ฌธ์ ์์์ ๋ง๋ ํผ์ฆ์ 2์ฐจ์ ๋ฆฌ์คํธ๋ฅผ 90๋์ฉ ํ์ ํด๋ณด๋ฉด์ ๋น์นธ๊ณผ ์ผ์นํ๋์ง ํ์ธํด์ผ ํฉ๋๋ค. ๋ฐ๋ผ์ 2์ฐจ์ ๋ฆฌ์คํธ๋ฅผ ์ค๋ฅธ์ชฝ์ผ๋ก 90๋์ฉ ํ์ ํ๋ rotate()
ํจ์๋ฅผ ๋ง๋ค์์ต๋๋ค. ์ด๋, ๋ฌธ์ ์์ ํผ์ฆ๋ก ์ฑ์ด ๋น์นธ์ ๊ฐ์๋ฅผ ๋ฌผ์ด๋ณด๊ธฐ ๋๋ฌธ์ rotate
ํจ์์์ ํผ์ฆ์ ํฌ๊ธฐ, ์ฆ 2์ฐจ์ ๋ฆฌ์คํธ์์ 1์ ๊ฐ์๋ ํจ๊ป ์นด์ดํธํ์ฌ ๋ฆฌํดํด์ค๋๋ค
def rotate(puzzle):
rotate = [[0] * len(puzzle) for _ in range(len(puzzle[0]))]
count = 0
for i in range(len(puzzle)):
for j in range(len(puzzle[i])):
if puzzle[i][j] == 1:
count += 1
rotate[j][len(puzzle) - 1 - i] = puzzle[i][j]
return rotate, count
์ด์ solution
ํจ์์์ ์์์ ์ ์ ํ ๊ตฌํํด ๋์ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋ต์ ๋ฆฌํดํด๋ณด๊ฒ ์ต๋๋ค.
def solution(game_board, table):
answer = 0
empty_blocks = find_block(game_board, 0)
puzzles = find_block(table, 1)
for empty in empty_blocks:
filled = False
table = make_table(empty)
for puzzle_origin in puzzles:
if filled == True:
break
puzzle = make_table(puzzle_origin)
for i in range(4):
puzzle, count = rotate(puzzle)
if table == puzzle:
answer += count
puzzles.remove(puzzle_origin)
filled = True
break
empty_blocks
,puzzles
์ ๋น๊ณต๊ฐ๊ณผ ํผ์ฆ ์ ๋ณด๋ฅผ ์ ์ฅํฉ๋๋ค.- ๋น๊ณต๊ฐ์ ํ๋์ฉ ๋๋ฉด์ 2์ฐจ์ ๋ฆฌ์คํธ๋ก ๋ง๋ค๊ณ (
make_table()
) - ๋น๊ณต๊ฐ์ ๋ํด์
puzzle
๋ค์ ํ๋์ฉ ๋๋ฉด์ ๋ง์ฐฌ๊ฐ์ง๋ก 2์ฐจ์ ๋ฆฌ์คํธ๋ก ๋ง๋ค๊ณ 4๋ฒ ํ์ ์ํค๋ฉด์ ๋น๊ณต๊ฐ์ ๋ชจ์๊ณผ ํผ์ฆ์ ๋ชจ์์ด ์ผ์นํ๋์ง ํ์ธํฉ๋๋ค. (๋ ๊ฐ์ 2์ฐจ์ ๋ฆฌ์คํธ(table
(๋น๊ณต๊ฐ)์puzzle
(ํผ์ฆ))์ด ์ผ์นํ๋์ง ํ์ธ) filled
๋ณ์๋ ํด๋น ๋น๊ณต๊ฐ์ด ์ด๋ฏธ ์ฑ์์ก๋์ง๋ฅผ ํ์ธํ๋ ๋ณ์๋ก,filled
๊ฐTrue
์ด๋ฉดpuzzle
์ ํ์ธํ์ง ์์ต๋๋ค.puzzles.remove(puzzle_origin)
์ผ๋ก ํผ์ฆ์ ๋น๊ณต๊ฐ์ ์ฑ์ ์ ๋puzzles
์์ ์ ๊ฑฐํ์ฌ ๋ค์ ๋น๊ณต๊ฐ์์ ์ค๋ณต๋์ด ์ฑ์์ง์ง ์๋๋ก ํฉ๋๋ค.
๐ฑ ์ ๋ต ์ฝ๋
# !/usr/bin/env python
# -*- coding: utf-8 -*-
# programmers ํผ์ฆ์กฐ๊ฐ์ฑ์ฐ๊ธฐ
from collections import deque
dx = [0, 0, -1, 1]
dy = [-1, 1, 0, 0]
# board์ puzzle์ ๊ฐ๊ฐ ๋น๊ณต๊ฐ๊ณผ ๋ธ๋ญ์ ์ฐพ๋ ํจ์ (BFS)
def find_block(board, f):
empty_board_list = []
visited = [[False] * len(board[0]) for _ in range(len(board))]
for i in range(len(board)):
for j in range(len(board[i])):
if not visited[i][j] and board[i][j] == f:
queue = deque([(i, j)])
board[i][j] = f ^ 1
visited[i][j] = True
lst = [(i, j)]
while queue:
x, y = queue.popleft()
for _ in range(4):
nx, ny = x + dx[_], y + dy[_]
if nx < 0 or nx > len(board) - 1 or ny < 0 or ny > len(board) - 1:
continue
elif board[nx][ny] == f:
queue.append((nx, ny))
board[nx][ny] = f ^ 1
visited[nx][ny] = True
lst.append((nx, ny))
empty_board_list.append(lst)
return empty_board_list
# block์ ์ธ๋ฑ์ค๋ค๋ก table์ ๋ง๋๋ ํจ์
def make_table(block):
x, y = zip(*block)
c, r = max(x) - min(x) + 1, max(y) - min(y) + 1
table = [[0] * r for _ in range(c)]
for i, j in block:
i, j = i - min(x), j - min(y)
table[i][j] = 1
return table
# ์ค๋ฅธ์ชฝ์ผ๋ก 90๋ ํ์ ํ๋ ํจ์
def rotate(puzzle):
rotate = [[0] * len(puzzle) for _ in range(len(puzzle[0]))]
count = 0
for i in range(len(puzzle)):
for j in range(len(puzzle[i])):
if puzzle[i][j] == 1:
count += 1
rotate[j][len(puzzle) - 1 - i] = puzzle[i][j]
return rotate, count
def solution(game_board, table):
answer = 0
empty_blocks = find_block(game_board, 0)
puzzles = find_block(table, 1)
for empty in empty_blocks:
filled = False
table = make_table(empty)
for puzzle_origin in puzzles:
if filled == True:
break
puzzle = make_table(puzzle_origin)
for i in range(4):
puzzle, count = rotate(puzzle)
if table == puzzle:
answer += count
puzzles.remove(puzzle_origin)
filled = True
break
return answer
๋๊ธ