Notice
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
Tags
- 실버
- Java
- AI트랙
- dfs
- 패스트캠퍼스
- join
- 딕셔너리
- dp
- 정렬
- 오블완
- KT에이블스쿨
- Level1
- 프로그래머스
- python
- KT 에이블스쿨
- kt에이블스쿨5기
- 알고리즘
- Level2
- sql
- 파이썬
- BFS
- AIVLE
- 트리
- 그래프
- 백준
- 구현
- Level3
- spring
- 티스토리챌린지
- 골드
Archives
- Today
- Total
rose_brown
[프로그래머스] 퍼즐 조각 채우기 본문
1. 문제
https://school.programmers.co.kr/learn/courses/30/lessons/84021
2. 코드
python 1
from collections import deque
def bfs(x, y, visited, board, target):
queue = deque()
queue.append((x, y))
visited[x][y] = True
shape = [(x, y)]
directions = [(-1,0), (1,0), (0,-1), (0,1)]
while queue:
cx, cy = queue.popleft()
for dx, dy in directions:
nx, ny = cx+dx, cy+dy
if 0<=nx<len(board) and 0<=ny<len(board) and not visited[nx][ny] and board[nx][ny] == target:
visited[nx][ny] = True
queue.append((nx, ny))
shape.append((nx, ny))
return shape
def normalize(shape):
min_x = min(x for x, y in shape)
min_y = min(y for x, y in shape)
normalized = sorted((x - min_x, y - min_y) for x, y in shape)
return normalized
def rotate(shape):
return [ (y, -x) for x, y in shape ]
def extract_shapes(board, target):
visited = [[False]*len(board) for _ in range(len(board))]
shapes = []
for i in range(len(board)):
for j in range(len(board)):
if not visited[i][j] and board[i][j] == target:
shape = bfs(i, j, visited, board, target)
shapes.append(normalize(shape))
return shapes
def match_puzzle(empty, puzzle_shapes, used):
for i, puzzle in enumerate(puzzle_shapes):
if used[i]:
continue
rotated = puzzle
for _ in range(4):
rotated = rotate(rotated)
if normalize(rotated) == empty:
used[i] = True
return len(empty)
return 0
def solution(game_board, table):
empty_spaces = extract_shapes(game_board, 0)
puzzle_shapes = extract_shapes(table, 1)
used = [False] * len(puzzle_shapes)
answer = 0
for empty in empty_spaces:
answer += match_puzzle(empty, puzzle_shapes, used)
return answer
아이디어
- game_board의 0들은 퍼즐이 들어갈 빈 공간.
- table의 1들은 실제 퍼즐 조각.
- 퍼즐 조각을 회전시켜서(90, 180, 270 도 각각 확인) 빈 공간과 모양이 맞으면 끼워 넣을 수 있음.
- 좌표는 실제 위치와 무관하고, 모양이 일치하는지만 보면 됨.
- 이를 위해 모든 모양은 정규화(normalization) 해서 비교함.
풀이
- bfs( ) 함수
- game_board나 table에서 모양(조각)을 찾아주는 함수
- visited 배열을 사용해서 이미 확인한 위치는 다시 확인 안 하게 함 (중복 방지)
- 시작 좌표부터 queue에 넣고, 상하좌우 탐색하면서 같은 값(0 또는 1)인 좌표를 shape에 저장
- shape에는 연결된 좌표들이 담김 → 하나의 퍼즐 조각이나 빈칸 모양
- normalize( ) 함수
- bfs로 찾은 좌표 리스트는 실제 위치 기준(ex. (3,2), (4,2))이라, 위치는 다르지만 모양은 같을 수 있음
- 그래서 좌표 중 가장 작은 x, y 값을 0으로 만들고 → 나머지도 상대적으로 옮김
- 정렬해서 비교할 수 있게 정리함
- → 결국 (0,0)을 기준으로 모양만 남기기
- rotate( ) 함수
- 문제 조건에 뒤집기는 안 되지만 회전은 가능하다고 했음
- 퍼즐을 90도 돌리기 위해 (x, y) → (y, -x) 형태로 바꿈
- 4번 돌리면 0도, 90도, 180도, 270도 다 확인 가능함
- extract_shapes( ) 함수
- game_board나 table에서 각각 모양들 추출하는 함수
- game_board는 0인 부분을 찾아야 하고
- table은 1인 부분을 찾아야 함
- bfs 호출해서 shape 추출하고, normalize로 정리해서 담음
- match_puzzle(empty, puzzle_shapes)
- 하나의 빈칸 모양 (empty)에 대해 사용하지 않은 퍼즐 조각들과 비교
- 90도씩 4번 회전하며 비교, 동일하면 해당 인덱스 반환
- solution(game_board, table)
- game_board에서 0으로 된 빈칸 모양을 추출
- table에서 1로 된 퍼즐 모양을 추출
- 하나씩 매칭하며 사용한 퍼즐은 used로 체크
- 퍼즐이 맞으면 해당 칸 수만큼 누적해서 answer 증가
3. 메모
- 큰 틀에서 문제 해결 방안은 이해함(아이디어에 있는 내용)
- 실제로 어떻게 구현해야 할지 다소 어려웠음
- 검색을 통한 참조로 문제풀음
- BFS/DFS를 활용한 덩어리 탐색, normalize 개념, 좌표 회전 방식을 학습함
- 좌표 비교에서는 절대 위치가 아닌 상대 위치(0,0 기준)가 핵심임
- 회전 후에도 normalize를 다시 해줘야 비교가 정확해진다는 걸 놓쳐 초반에 오류 발생
- 유사 문제에 적용 가능한 패턴 정리: 모양 추출 → 정규화 → 회전 → 비교
'코딩 > 프로그래머스' 카테고리의 다른 글
[프로그래머스] 표 편집 (1) | 2025.07.11 |
---|---|
[프로그래머스] 합승 택시 요금 (5) | 2025.07.09 |
[프로그래머스] 메뉴 리뉴얼 (0) | 2025.04.24 |
[프로그래머스] 거스름돈 (0) | 2025.04.18 |
[프로그래머스] 문자열 나누기 (0) | 2025.04.08 |