개발 블로그
[Programmers/파이썬]프로그래머스(Lv.2) 프렌즈4블록 문제풀이 본문
프렌즈4블록
블라인드 공채를 통과한 신입 사원 라이언은 신규 게임 개발 업무를 맡게 되었다. 이번에 출시할 게임 제목은 "프렌즈4블록".
같은 모양의 카카오프렌즈 블록이 2×2 형태로 4개가 붙어있을 경우 사라지면서 점수를 얻는 게임이다.
만약 판이 위와 같이 주어질 경우, 라이언이 2×2로 배치된 7개 블록과 콘이 2×2로 배치된 4개 블록이 지워진다. 같은 블록은 여러 2×2에 포함될 수 있으며, 지워지는 조건에 만족하는 2×2 모양이 여러 개 있다면 한꺼번에 지워진다.
블록이 지워진 후에 위에 있는 블록이 아래로 떨어져 빈 공간을 채우게 된다.
만약 빈 공간을 채운 후에 다시 2×2 형태로 같은 모양의 블록이 모이면 다시 지워지고 떨어지고를 반복하게 된다.
위 초기 배치를 문자로 표시하면 아래와 같다.
TTTANT
RRFACC
RRRFCC
TRRRAA
TTMMMF
TMMTTJ
각 문자는 라이언(R), 무지(M), 어피치(A), 프로도(F), 네오(N), 튜브(T), 제이지(J), 콘(C)을 의미한다
입력으로 블록의 첫 배치가 주어졌을 때, 지워지는 블록은 모두 몇 개인지 판단하는 프로그램을 제작하라.
입력 형식
- 입력으로 판의 높이 m, 폭 n과 판의 배치 정보 board가 들어온다.
- 2 ≦ n, m ≦ 30
- board는 길이 n인 문자열 m개의 배열로 주어진다. 블록을 나타내는 문자는 대문자 A에서 Z가 사용된다.
출력 형식
입력으로 주어진 판 정보를 가지고 몇 개의 블록이 지워질지 출력하라.
입출력 예제
mnboardanswer
4 | 5 | ["CCBDE", "AAADE", "AAABF", "CCBBF"] | 14 |
6 | 6 | ["TTTANT", "RRFACC", "RRRFCC", "TRRRAA", "TTMMMF", "TMMTTJ"] | 1 |
사고 흐름
처음에는 dfs나 bfs로 풀려고 했다. 그런데 2*2 블록 형식을 맞추기가 어려웠고 어떻게 해야할지 고민했다
-> 그러다 n과 m의 범위가 30이하라서 배열 크기가 크지 않다고 생각해 그냥 하나씩 돌며 확인해야겠다고 생각
-> for문으로 각 원소를 돌며 만약 2*2 블록 안이 다 같으면 check리스트에서 0으로 표시한다 (터졌다는 뜻)
-> 그리고 0으로 터진 부분들을 재정렬해줘야 하는데 이 부분이 어려웠다.
-> 새로운 board를 만들어 터진부분(0)은 위에있는 블럭을 가져오는 식으로 만들었다.
-> 그리고 그 과정을 반복하며 더이상 터지지못할때까지 진행한다
문제 핵심과 알고리즘
문제에 주어진 조건으로 구현하는 문제.
def solution(m, n, board):
answer = 0
while True :
origin=block(m,n,board)
new=block(m,n,origin)
if origin==new :
break
board=new
for i in new :
answer+=i.count('')
return answer
def block(m, n, board) :
check=[[1 for j in range(n)] for i in range(m)] #터지는 블록 0으로 표시
new_board=[["" for j in range(n)] for i in range(m)] #재정렬할 새로운 board
for x in range(m-1) :
for y in range(n-1) :
target=board[x][y] #타겟이 될 현재 위치의 캐릭터
if board[x+1][y]==target and board[x][y+1]==target and board[x+1][y+1]==target :
check[x][y],check[x+1][y],check[x][y+1],check[x+1][y+1]=0,0,0,0
#2*2 블럭이 다 동일하면 0으로 표시
#board를 돌며
#0인 부분(터질부분)은 위에있는 원소를 가져오고,
#1인 부분은 그대로 board 원소를 가져온다
for i in range(n-1, -1, -1) :
for j in range(m-1, -1, -1) :
if check[j][i]==0 :
temp=j
while check[temp][i]==0 and temp>=0:
temp-=1
if temp>=0 :
new_board[j][i]=board[temp][i]
check[temp][i]=0
else :
new_board[j][i]=board[j][i]
return new_board
문제 풀면서 헤맸던 부분
1. 터진 부분을 재정렬하는 부분
터진 후 배열을 재정렬할때가 어려웠다. 이 방법 저 방법 시도한 뒤, 그냥 완전 새로운 배열을 만들었다.
다른 사람 풀이 참고하여 배운 점
세부적인 구현 방법은 다르지만 다들 비슷하게 2*2블럭이 있으면 check하고 그 부분에서 재정렬했다.
총평
풀 때는 어떻게 풀어야 할지 조금 막막했는데, 지금 와서 보니 별거 아니다. 재정렬하는 부분을 대수롭지 않게 생각했는데 그 부분을 생각하는게 제일 오래걸렸다. 뭐든 코드를 짜기전 설계하는 단계를 소홀히 하지말자..
'Algorithm' 카테고리의 다른 글
[Programmers/파이썬]프로그래머스(Lv.1) 키패드 누르 문제풀이 (0) | 2023.03.03 |
---|---|
[백준/파이썬] 1431번<시리얼 번호> 문제 풀이 (0) | 2023.03.03 |
[Programmers/파이썬]프로그래머스(Lv.2) 파일명 정렬 문제풀이 (0) | 2023.03.02 |
[백준/파이썬] 1181번<단어 정렬> 문제 풀이 (0) | 2023.03.01 |
[Programmers/파이썬]프로그래머스(Lv.2) 오픈채팅방 문제풀이 (0) | 2023.03.01 |