프로그래머스 프렌즈4블록 (python)

박노정·2021년 6월 21일
0

알린이의 알고리즘

목록 보기
9/15
post-custom-banner

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

블라인드 공채를 통과한 신입 사원 라이언은 신규 게임 개발 업무를 맡게 되었다. 이번에 출시할 게임 제목은 "프렌즈4블록".
같은 모양의 카카오프렌즈 블록이 2×2 형태로 4개가 붙어있을 경우 사라지면서 점수를 얻는 게임이다.

이문제는 이차원배열을 이용해서 푸는 문제이다.
그래서 그런지 인덱싱이 정말 중요했다. (중간에 인덱싱을 잘못해서 인덱싱 에러잡는다고 혼났다.)

그래도 어떻게 인덱싱에러를 잡고나니 바로 통과했다.

전체 풀이

def solution(m, n, board):
    answer = 0
    boards = [[0] * n for i in range(m)]
    for i in range(m):
        for j in range(n):
            boards[i][j] = board[i][j]

    done = set()
    flag = True
    while flag:
        for i in range(m - 1):
            for j in range(n - 1):
                if boards[i][j] == boards[i][j + 1] == boards[i + 1][j] == boards[i + 1][j + 1] != 0:
                    done.add((i, j))
                    done.add((i, j + 1))
                    done.add((i + 1, j))
                    done.add((i + 1, j + 1))
        if not done:
            flag = False
        while done:
            a, b = done.pop()
            boards[a][b] = 0
            answer += 1

        for i in range(m - 1, -1, -1):
            for j in range(n - 1, -1, -1):
                if boards[i][j] == 0:
                    for a in range(i - 1, -1, -1):
                        if boards[a][j] != 0:
                            boards[i][j], boards[a][j] = boards[a][j], boards[i][j]
                            break
    return answer

이렇게 풀었다.

상세 풀이

먼저 string값으로 되어있는 것들을 인덱싱하기 편하게 하기위해 2차원배열의 형태로 바꿔줬다.

boards = [[0] * n for i in range(m)]
    for i in range(m):
        for j in range(n):
            boards[i][j] = board[i][j]

done에 터질 블럭들의 좌표를 담아준다.
여기서 인덱싱은 가로세로 1개 적게 했는데 그 이유는 현재 좌표를 기준으로 오른쪽 아래로 정사각형을 그리며 검사하기 때문이다.

    done = set()
    flag = True
    while flag:
        for i in range(m - 1):
            for j in range(n - 1):
                if boards[i][j] == boards[i][j + 1] == boards[i + 1][j] == boards[i + 1][j + 1] != 0:
                    done.add((i, j))
                    done.add((i, j + 1))
                    done.add((i + 1, j))
                    done.add((i + 1, j + 1))

그다음 터질 블럭이 없으면 아예 검사를 종료하고 있다면 그값을 보드에 0 으로 만들어주고 answer에 1 더해준다 (터진블럭세리기)

	if not done:
            flag = False
        while done:
            a, b = done.pop()
            boards[a][b] = 0
            answer += 1

마지막으로는 빈자리에 블럭들을 채워야한다.
이때는 거꾸로 올라가면서 검사한다.
그러다가 0을 찾을 경우, 그 열을 검사하여 제일 처음 만나는 블럭과 자리를 바꾸면서 블럭을 내리는것을 구현했다.

 for i in range(m - 1, -1, -1):
           for j in range(n - 1, -1, -1):
               if boards[i][j] == 0:
                   for a in range(i - 1, -1, -1):
                       if boards[a][j] != 0:
                           boards[i][j], boards[a][j] = boards[a][j], boards[i][j]
                           break

후기

생각보다 구현하는데 오래걸렸다. 그리고 오랜만에 이차원배열을 해보니까 인덱싱에서 헷갈렸는데, 자주 풀면서 이런점을 개선해나가야겠다.

profile
성장스택 쌓고있는 개발자🏋
post-custom-banner

0개의 댓글