본문 바로가기
개발/문제풀이

프로그래머스 '[1차] 프렌즈4블록' 파이썬 풀이

by beomcoder 2023. 5. 26.
728x90
반응형
https://school.programmers.co.kr/learn/courses/30/lessons/17679
 

프로그래머스

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

programmers.co.kr

 

"""
각 문자는 라이언(R), 무지(M), 어피치(A), 프로도(F),
네오(N), 튜브(T), 제이지(J), 콘(C)을 의미한다.

입력으로 블록의 첫 배치가 주어졌을 때, 지워지는 블록은 
모두 몇 개인지 판단하는 프로그램을 제작하라.
"""
def solution(m, n, b):
    b = [[[0, b[y][x], 0] for y in range(m)] for x in range(n)]
    ispoped = True
    while ispoped:
        ispoped = False
        for y in range(n-1):
            for x in range(m-1):
                if sum([b[y][x][0], b[y][x+1][0], b[y+1][x][0], b[y+1][x+1][0]]) == 0:
                    if len(set([b[y][x][1], b[y][x+1][1], b[y+1][x][1], b[y+1][x+1][1]])) == 1:
                        ispoped = True
                        b[y][x][2], b[y][x+1][2], b[y+1][x][2], b[y+1][x+1][2] = 1, 1, 1, 1
            
        for y in range(n-1):
            for x in range(m-1):
                b[y][x][0], b[y][x+1][0], b[y+1][x][0], b[y+1][x+1][0] = b[y][x][2], b[y][x+1][2], b[y+1][x][2], b[y+1][x+1][2]
                
        for i in range(len(b)):
            b[i].sort(key=lambda x: -x[0])
            
    answer = 0
    for y in range(n):
            for x in range(m):
                answer += 1 if b[y][x][0] == 1 else 0
    return answer
   
"""
0~2단계를 차례대로 풀고 있는데 2단계 중 풀릴 것 같은데 싶은 문제중
제일 깔끔하지 못하게 푼 문제이다..

처음에는 그대로 풀어보려고 했는데 삭제처리를 어떻게 해줘야할지 몰라서
리스트를 행과 열을 서로 바꾸어 풀었다.
행과 열을 바꾸면 지워질 것들을 쉽게 지울 수 있을 것이라 생각했다.

풀다가 지워지는걸 바로 지우면 안되고 전체블록을 검사하고 지워야한다는걸 알았다.
바로바로 지워버리면 네모가 겹쳐지는 부분이 처리가 안되었다.

b = [[[0, b[y][x], 0] for y in range(m)] for x in range(n)]

그래서 여기서 [0, b[y][x], 0] 이 부분에서 0번째 인덱스는 지워진 블록,
1번째 인덱스는 행과 열이 바뀐 블록, 2번째 인덱스는 지워져야할 블록을
표시하기 위해 3개를 사용했다.

ispoped = True
    while ispoped:
    
이 부분은 더이상 지워지는 블록이 없다면 while문을 끝내기 위해 변수를 선언했다.

if sum([b[y][x][0], b[y][x+1][0], b[y+1][x][0], b[y+1][x+1][0]]) == 0:
    if len(set([b[y][x][1], b[y][x+1][1], b[y+1][x][1], b[y+1][x+1][1]])) == 1:

이 부분은 블록 4개가 모두 지워진 블록이 아니고, 4개의 블록이 같은 블록이면 이라는 뜻이다.
첫번째 if문은 4개의 블록의 0번째 인덱스를 모두 더해 0이면 모두 살아있는 블록이다.
지워진 블록은 1로 바꾸어주기 때문이다.

그리고 두번째 if문은 블록 4개를 set으로 처리하면 중복은 지워지기 때문에
길이가 1이라면 모두 같은 블록이라는 뜻이다.

ispoped = True
b[y][x][2], b[y][x+1][2], b[y+1][x][2], b[y+1][x+1][2] = 1, 1, 1, 1

if문 2개를 모두 통과했다면 지워진 블록이 있다는 변수를 true로 바꿔주고,
4개의 블록을 지워져야할 블록이라고 표시해준다.
바로 지워버리면 겹치는 부분의 네모가 있을때 지워주지 못하기 때문에
임시로 2번째 인덱스에 표시를 해두었다.

 for y in range(n-1):
    for x in range(m-1):
        b[y][x][0], b[y][x+1][0], b[y+1][x][0], b[y+1][x+1][0] 
        = b[y][x][2], b[y][x+1][2], b[y+1][x][2], b[y+1][x+1][2]
                
그리고 모든 블록을 검사하고 나서 다시 지워져야할 블록을 검사해서
지워진 블록으로 바꾸어준다.

for i in range(len(b)):
    b[i].sort(key=lambda x: -x[0])

마지막으로 지워진블록은 제일 위로 올라가고 남은 블록은 밑으로 가야하기 때문에
리스트(b)를 돌면서 각 리스트의 0번째인덱스를 비교하여 0이면 밑으로 내려가고,
1이면 위로 올라가게 정렬시켜주었다.

그리고 while문을 빠져나오면 리스트들의 0번째 인덱스를 더해주어
최종 지워진블록의 갯수를 리턴시켜주었다.
"""
728x90
반응형

댓글