본문 바로가기
코딩 테스트/프로그래머스

[프로그래머스 - Python] Lv.2 프렌즈 4블록

by 오엥?은 2023. 3. 9.
반응형
  • 문제

https://school.programmers.co.kr/learn/courses/30/lessons/17679

 

프로그래머스

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

programmers.co.kr

 

  • 풀이
import copy

def solution(m, n, board):
    # 1
    new_board = [list(board[x]) for x in range(0, len(board))]  # 문자열 분리하여 2차원 배열로 바꾸기

    count = 1
    new_board_temp = copy.deepcopy(new_board)
    while count != 0:
        count = 0

        # 2
        for x in range(0, m - 1):
            for y in range(0, n - 1):
                if new_board[x][y] != '':
                    if new_board[x][y] == new_board[x][y + 1] == new_board[x + 1][y] == new_board[x + 1][y + 1]:
                        new_board_temp[x][y] = ""
                        new_board_temp[x][y + 1] = ""
                        new_board_temp[x + 1][y] = ""
                        new_board_temp[x + 1][y + 1] = ""

                    if new_board_temp[x][y] == "":
                        count += 1

        # 3
        num = 1
        while num != 0:
            num = 0
            for x in range(1, m):
                for y in range(0, n):
                    if new_board_temp[x][y] == '':
                        a = copy.deepcopy(new_board_temp[x][y])
                        new_board_temp[x][y] = copy.deepcopy(new_board_temp[x - 1][y])
                        new_board_temp[x - 1][y] = ''
                        b = copy.deepcopy(new_board_temp[x][y])

                        if a != b:
                            num += 1

        new_board = copy.deepcopy(new_board_temp)


    # 4
    count = 0
    for x in range(0, m):
        for y in range(0, n):
            if new_board[x][y] == '':
                count += 1

    return count

# 1

일단 board가 1차원 배열에 담긴 문자열로 주어지는데 한 글자 한 글자 따로 봐야되기 때문에 문자열을 분리하여 2차원 배열로 담아줬다.

a = 'Hello' 를 list(a) 해주면 ['H', 'e', 'l', 'l', 'o'] 이렇게 되기때문에 list(board[x]) 했다. 그걸 변수 new_board 에 담았다.

 

4개가 정사각형 모양으로 만나면 터지는건데 위 그림처럼 겹치는 경우가 있을 수 있다. 터지면 ''로 바꿔줄건데 new_board 에서 바꿔버리면 겹치는 부분을 해결할 수 없어서 임시로 new_board_temp 를 만들고 ''으로 바꾸는 작업은 new_board_temp 에서 할 거다.

 

처음엔 new_board_temp = new_borad 라고 했는데 이러니까 new_board_temp 를 바꾸면 new_board 까지 바껴버렸다. 이 문제 해결하려면 deep copy를 해야했다. 파이썬 웃기네 copy.deepcopy(복사할 거) 이거 적으면 된다.

 

 

#2

while 반복문 안에서 해결할 거다. while 문의 조건은 count 가 0이 아니면 도는 건데 시작부터 count = 0 으로 한 다음 같은 그림이 팡 터지면 count += 1 해 주는거다. 반복문 다 돌았을 때도 count = 0 이면 팡 터진게 하나도 없다는 뜻이기 때문에 멈춘다. 

 

new_board 배열 반복문을 돌린다.

new_board[x][y] == new_board[x][y + 1] == new_board[x + 1][y] == new_board[x + 1][y + 1]

이렇게 4개가 모두 같아야 정사각형 모양으로 팡 터지는 거다. 근데 그 위에

new_board[x][y] != ''

이 조건을 왜 달았냐면 '' 일 때도 팡 터져버려서 암것도 없으면서 터지는 척 해서 그랬다. 빈칸이 정사각형모양으로 모인 건 안 된다. 그래서 조건은 빈칸이 아닐 때다.

 

new_board 의 요소가 정사각형 모양으로 같은 그림이면 new_board_temp 가 터진다. 만약 new_board_temp 가 터졌으면 count 를 올려준다.

 

 

#3

이 부분 때문에 오래걸렸다.

터지면 내려와서 채워야한다. 그럼 반복문을 돌려서 x 번째가 빈칸이면 x-1 번째 요소랑 바꿔치기 하고 x-1 번째 요소를 빈칸으로 바꾸면 된다.

for x in range(1, m):
    for y in range(0, n):
        if new_board_temp[x][y] == '':
            new_board_temp[x][y] = copy.deepcopy(new_board_temp[x - 1][y])
            new_board_temp[x - 1][y] = ''

처음엔 이렇게 했다. 이러고 제출하니까 예제 답은 맞는데 제출하면 계속 실패했다. 계속 출력하면서 확인해보니까 이렇게 하면 중간에 빵꾸날 수도 있다!!

 

만약 1, 2번째에 있고 3, 4번째 터졌고 5번에 있다고 생각해 보면 2는 터지지 않았기 때문에 1에서 블록이 내려오지 않는다. 근데 3번은 비었기 때문에 2번에서 블록이 내려온다. 4번도 비어서 3번에서 블록이 내려오고 5번은 블록이 있기 때문에 그대로다. 그럼 결국 블록이 1, 4, 5 에 있는 거다. 완전 빵꾸났잖아

 

그래서 이 부분도 while 반복문을 돌려줬다. 

while 문의 조건은 num != 0 이다. 만약 블록이 내려가면 num += 1 을 할 거기 때문에 num = 0 이면 블록이 움직이지 않은 거다.

 

만약 new_board_temp[x][y] 가 빈칸이면 위에서 블록이 내려와야 한다. new_board_temp[x - 1][y] 와 바꾼다. new_board_temp[x - 1][y] 은 그럼 빈칸이 된다. new_board_temp[x][y] 가 바뀌기 전은 a 라고 두고, new_board_temp[x][y] 가 바뀌고 난 후는 b 로 둔다. 만약에 둘이 다르면 '' -> '' 은 아니란 소리다. 블록이 내려왔다는 소리다. 그럼 num += 1 을 해준다.

 

반복문이 끝나면 new_board 도 바꿔준다.

 

 

#4

반복문에서 빠져나오면 터질 거 다 터졌다는 말이 된다. 그럼 또 반복문을 돌려서 터진부분 ''을 찾아서 개수 세면 된다.

 

 

 

  • 다른 사람 풀이
for i in x2:
    count += i.count('')
return count

마지막에 터진부분 세는거 이렇게 해놨던데 넘 간단하다. 써먹어야쥥

 

반응형