본문 바로가기

알고리즘/프로그래머스

2019 카카오 블라인드 코딩 테스트 - 블록게임, 파이썬

1. 문제

- 테트리스에서 개념을 가져온 문제로 세부사항은 프로그래머스 문제 참고

 

2. 풀이

- 이 문제는 마지막 문제인데다가 쉬워보여서 얼렁뚱땅 풀어보다 틀렸다. 

- 아래 테스트케이스에서 답이 1이 나와야 한다.  [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 2, 2, 0, 0, 0, 0, 0], [0, 0, 0, 2, 1, 0, 0, 0, 0, 0], [0, 0, 0, 2, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

- 또한 테스트케이스 14, 15, 16, 17번이 왜 틀렸나 했더니 반복문 중에 블록 숫자만큼 반복해줘야 하는데 적당히 N만큼 반복해줬다 틀렸다(예제 문제만 보고 N이 블록 수보다 많을 것이라고 지레짐작한 문제)

- 게으름 때문에 결국 더 돌아돌아 오래걸렸다. 

- 문제에서 요구하는 것을 구현해야 한다. 

 

3. 코드

 

from collections import defaultdict

def solution(board):
    dic = defaultdict(list)
    N = len(board)
    # i = 행, y좌표 / j = 열, x좌표
    # 가능 후보 블록 위로 불가능 블록이 막고있는지 테스트해야 하는데 세로 배열 접근을 위해 b 정의
    b = [[[0] for _ in range(N)] for _ in range(N)]
    for i in range(N) :
        for j in range(N) :
            b[j][i] = board[i][j]
            if not board[i][j] == 0 :
            	#블록 번호를 키로 좌표를 딕셔너리에 저장해줌
                dic[board[i][j]].append([i, j])
    cnt = 0
    # 가능 블록이 위를 막고 있는 경우 불가능 처리 되었던 블록도 가능할 수 있기 때문에 블록 수만큼 반복
    l = len(dic.keys())
    for i in range(l) :
        for key in dic.keys() :
        	# 만약 가능 블록으로 판명 난다면 cnt 1을 더해준 후 블록을 제거해주고 딕셔너리에서도 제거해줌
            if val_check(dic[key], b, key) :
                cnt += 1
                for dot in dic[key] :
                    b[dot[1]][dot[0]] = 0
                    board[dot[0]][dot[1]] = 0
                del dic[key]
                break
    return cnt

def val_check(arr, b, key) :
    x_set = []
    y_set = []
    
    for dot in arr :
        x_set.append(dot[1])
        y_set.append(dot[0])
        
    if not val_block(y_set) :
        return False
    else :
        y = max(y_set)
        for block_x in x_set :
        	# 위가 채워진 경우 그 위에 불가능 블록이 막고 있어도 상관이 없음, 위 테스트케이스 참조
            if x_set.count(block_x) > 1:
                continue
            # 위가 빈 경우 그 위로는 전부 비어있어야 함(= 0으로 채워져 있어야 함)
            if not b[block_x][:y].count(0) == y :
                return False
        return True
# 아래가 채워져있고 위가 비어있는 모양의 5가지 블록을 구별해내기 위한 함수
def val_block(arr) :
    if (min(arr) + max(arr))* 2 < sum(arr) :
        return True
    return False

4. 개선점

- 실제 시험이 아니기 때문에 얼렁뚱땅 문제만 풀지 말고 변형된 문제가 나와도 처리할 수 있도록 묻는 질문이 무엇인지(= 요구하는 능력이 무엇인지) 생각해보자