알고리즘/프로그래머스

[위클리 챌린지] 3주차

래울 2021. 8. 29. 19:09

https://programmers.co.kr/learn/courses/30/lessons/84021#

 

코딩테스트 연습 - 3주차

[[1,1,0,0,1,0],[0,0,1,0,1,0],[0,1,1,0,0,1],[1,1,0,1,1,1],[1,0,0,0,1,0],[0,1,1,1,0,0]] [[1,0,0,1,1,0],[1,0,1,0,1,0],[0,1,1,0,1,1],[0,0,1,0,0,0],[1,1,0,1,1,0],[0,1,0,0,0,0]] 14 [[0,0,0],[1,1,0],[1,1,1]] [[1,1,1],[1,0,0],[0,0,0]] 0

programmers.co.kr

 

간소화랑 효율성 고려안하고 짜서 그런지 코드가 좀 난잡하다.

 

- 풀이

 

1. table에 대해 각각의 블럭에 대해 아래와 같은 배열을 만든다.

0 0 0 0 0 0
0 0 1 0 0 0
0 1 1 0 0 0
0 0 1 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0

 

2. game_board에 대해서도 위와 같이 배열을 만든다.

3. 2번에서 만든 빈칸배열(board)에 대해 맞는 블럭을 찾는다.

4. 블럭과 빈칸의 크기가 같고 check()함수가 True라면, answer에 합산, 그리고 한 블럭이 두개이상의 빈칸에 들어가는 것을 막기위해 삭제

5. check함수

  - block을 회전시키면서 맞는지 비교

  - 블럭과 빈칸의 위치를 list1, list2에 좌표형태로 추가

EX) 위와 같은 'ㄱ'자 블럭과 빈칸을 나타내는 두 배열에 대해

list1 = [[0,0], [0,1], [1,0]]

list2 = [[1,1], [1,2], [2,1]] 

이라 할 때, list1 - list2 = [[-1,-1], [-1,-1], [-1,-1]]

list1[:, 0]값들이 다 같고, list2[:, 1]값도 다 같으면 같은 모양이라고 할 수 있다.

* unique() : 유일한 값들을 반환한다.

 

 

import numpy as np
def solution(game_board, table):
    answer = 0  

### table블럭 구하기 ###
    blocks = []
    for i in range(len(table)):
        for j in range(len(table[i])):
            if table[i][j]: #블럭이 있으면
                table[i][j] = 0
                queue = [[i, j]]
                block = np.zeros((len(table), len(table)))
                block[i][j] = 1
                while queue:
                    x, y = queue[0][0], queue[0][1]
                    del queue[0] 
                    if y+1 < len(table[x]) and table[x][y+1]==1: #좌
                        queue.append([x, y+1])
                        table[x][y+1] = 0
                        block[x][y+1] = 1
                    if y > 0 and table[x][y-1]==1: #우
                        queue.append([x, y-1])
                        table[x][y-1] = 0
                        block[x][y-1] = 1
                    if x > 0 and table[x-1][y]==1: #상
                        queue.append([x-1, y])
                        table[x-1][y] = 0
                        block[x-1][y] = 1
                    if x+1 < len(table) and table[x+1][y]==1: #하
                        queue.append([x+1, y])
                        table[x+1][y] = 0
                        block[x+1][y] = 1
                blocks.append(np.array(block))

### game_board블럭 구하기 ###                
    cnt = 0 #debug
    for i in range(len(game_board)):
        for j in range(len(game_board[i])):
            if not game_board[i][j]: #빈칸이면
                game_board[i][j] = 1
                queue = [[i, j]]
                block = np.zeros((len(game_board), len(game_board)))
                block[i][j] = 1
                while queue:
                    x, y = queue[0][0], queue[0][1]
                    del queue[0] 
                    if y+1 < len(game_board[x]) and game_board[x][y+1]==0: #좌
                        queue.append([x, y+1])
                        game_board[x][y+1] = 1
                        block[x][y+1] = 1
                    if y > 0 and game_board[x][y-1]==0: #우
                        queue.append([x, y-1])
                        game_board[x][y-1] = 1
                        block[x][y-1] = 1
                    if x > 0 and game_board[x-1][y]==0: #상
                        queue.append([x-1, y])
                        game_board[x-1][y] = 1
                        block[x-1][y] = 1
                    if x+1 < len(game_board) and game_board[x+1][y]==0: #하
                        queue.append([x+1, y])
                        game_board[x+1][y] = 1
                        block[x+1][y] = 1
                cnt += 1    
### 빈칸에 맞는 블럭인지 체크 후 answer에 추가 ###
                for k in range(len(blocks)):
                    if blocks[k].sum()==np.array(block).sum() and check(blocks[k], block):  #테이블, 보드
                        answer += blocks[k].sum()
                        block = []
                        del blocks[k]
                        break
    return answer

### 블럭을 돌려가며, 칸에 맞는지 체크 ###
def check(block, board):
    for k in range(4):  #rotate 90 180 270 360
        block = np.rot90(block)
        list1, list2 = [], []
        for i in range(len(block)):
            for j in range(len(block[i])):
                if block[i][j] == 1:
                    list1.append([i, j])
                if board[i][j] == 1:
                    list2.append([i, j])
        temp = np.array(list1) - list2  #np.array는 리스트간의 연산이 가능
        if len(np.unique(temp[:,0]))==1 and len(np.unique(temp[:,1]))==1:
            print(temp)
            return True
    return False