programmers.co.kr/learn/courses/30/lessons/42894
코딩테스트 연습 - 블록 게임
[[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,4,0,0,0],[0,0,0,0,0,4,4,0,0,0],[0,0,0,0,3,0,4,0,0,0],[0,0,0,2,3,0,0,0,5,5],[1,2,2,2,3,3,0,0,0,5],[1,1,1,0,0,0,0,0,0,5]] 2
programmers.co.kr
"""
블록게임
빨간색 블록의 세 번째, 네 번째 케이스
노란색 블록의 두 번째, 세 번째 케이스
하늘색 블록의 첫 번째 케이스
들만 없앨 수 있다.
"""
# 빨간 블록 세 번째 케이스
def red_third_case(check_start_row, check_start_col, board, block_number, N):
# 왼쪽에서 오른쪽으로, 위에서 아래로 검사하므로,
# 현재 이 블록을 처음 찾은 위치를 포함하여
# 오른쪽으로 세 칸, 아래쪽으로 두 칸의 직사각형 공간이 보드상에 존재하는지 먼저 확인한다.
for row in range(check_start_row, check_start_row + 2):
for col in range(check_start_col, check_start_col + 3):
if not (0 <= row <= N - 1 and 0 <= col <= N - 1):
return False
# 빨간 블록 세 번째 케이스의 형태이다.
red_third_block_with_black_blocks = [
[block_number, -2, -2],
[block_number, block_number, block_number]
]
# 현재 검사하는 위치의 블록이 빨간 블록 세 번째 케이스의 형태인지 확인한다.
for row in range(2):
for col in range(3):
if board[check_start_row + row][check_start_col + col] \
!= red_third_block_with_black_blocks[row][col]:
return False
# 형태가 맞다면, 검은 블록을 포함하여 해당 블록을 모두 0으로 삭제한다.
for row in range(check_start_row, check_start_row + 2):
for col in range(check_start_col, check_start_col + 3):
board[row][col] = 0
return True
# 빨간 블록 네 번째 케이스
def red_fourth_case(check_start_row, check_start_col, board, block_number, N):
# 왼쪽에서 오른쪽으로, 위에서 아래로 검사하므로,
# 현재 이 블록을 처음 찾은 위치를 포함하여
# 왼쪽으로 두 칸, 아래쪽으로 세 칸의 공간이 보드상에 존재하는지 먼저 확인한다.
for row in range(check_start_row, check_start_row + 3):
for col in range(check_start_col, check_start_col - 2, -1):
if not (0 <= row <= N - 1 and 0 <= col <= N - 1):
return False
# 빨간 블록 네 번째 케이스의 형태이다.
red_fourth_block_with_black_blocks = [
[-2, block_number],
[-2, block_number],
[block_number, block_number]
]
# 현재 검사하는 위치의 블록이 빨간 블록 네 번째 케이스의 형태인지 확인한다.
for row in range(3):
for col in range(2):
if board[check_start_row + row][check_start_col - 1 + col] \
!= red_fourth_block_with_black_blocks[row][col]:
return False
# 형태가 맞다면, 검은 블록을 포함하여 해당 블록을 모두 0으로 삭제한다.
for row in range(check_start_row, check_start_row + 3):
for col in range(check_start_col, check_start_col - 2, -1):
board[row][col] = 0
return True
# 노란 블록 두 번째 케이스
def yellow_second_case(check_start_row, check_start_col, board, block_number, N):
# 왼쪽에서 오른쪽으로, 위에서 아래로 검사하므로,
# 현재 이 블록을 처음 찾은 위치를 포함하여
# 오른쪽으로 두 칸, 아래쪽으로 세 칸의 공간이 보드상에 존재하는지 먼저 확인한다.
for row in range(check_start_row, check_start_row + 3):
for col in range(check_start_col, check_start_col + 2):
if not (0 <= row <= N - 1 and 0 <= col <= N - 1):
return False
# 노란 블록 두 번째 케이스의 형태이다.
yellow_second_block_with_black_blocks = [
[block_number, -2],
[block_number, -2],
[block_number, block_number]
]
# 현재 검사하는 위치의 블록이 노란 블록 두 번째 케이스의 형태인지 확인한다.
for row in range(3):
for col in range(2):
if board[check_start_row + row][check_start_col + col] \
!= yellow_second_block_with_black_blocks[row][col]:
return False
# 형태가 맞다면, 검은 블록을 포함하여 해당 블록을 모두 0으로 삭제한다.
for row in range(check_start_row, check_start_row + 3):
for col in range(check_start_col, check_start_col + 2):
board[row][col] = 0
return True
# 노란 블록 세 번째 케이스
def yellow_third_case(check_start_row, check_start_col, board, block_number, N):
# 왼쪽에서 오른쪽으로, 위에서 아래로 검사하므로,
# 현재 이 블록을 처음 찾은 위치를 포함하여
# 왼쪽으로 세 칸, 아래쪽으로 두 칸의 공간이 보드상에 존재하는지 먼저 확인한다.
for row in range(check_start_row, check_start_row + 2):
for col in range(check_start_col, check_start_col - 3, -1):
if not (0 <= row <= N - 1 and 0 <= col <= N - 1):
return False
# 노란 블록 세 번째 케이스의 형태이다.
yellow_third_block_with_black_blocks = [
[-2, -2, block_number],
[block_number, block_number, block_number]
]
# 현재 검사하는 위치의 블록이 노란 블록 세 번째 케이스의 형태인지 확인한다.
for row in range(2):
for col in range(3):
if board[check_start_row + row][check_start_col - 2 + col] \
!= yellow_third_block_with_black_blocks[row][col]:
return False
# 형태가 맞다면, 검은 블록을 포함하여 해당 블록을 모두 0으로 삭제한다.
for row in range(check_start_row, check_start_row + 2):
for col in range(check_start_col, check_start_col - 3, -1):
board[row][col] = 0
return True
# 하늘색 블록 첫 번째 케이스
def skyblue_first_case(check_start_row, check_start_col, board, block_number, N):
# 왼쪽에서 오른쪽으로, 위에서 아래로 검사하므로,
# 현재 이 블록을 처음 찾은 위치를 포함하여
# 왼쪽 한 칸, 오른쪽 한 칸, 아래로 두 칸의 공간이 보드상에 존재하는지 먼저 확인한다.
for row in range(check_start_row, check_start_row + 2):
for col in range(check_start_col - 1, check_start_col - 1 + 3):
if not (0 <= row <= N - 1 and 0 <= col <= N - 1):
return False
# 하늘색 블록 첫 번째 케이스의 형태이다.
skyblue_first_block_with_black_blocks = [
[-2, block_number, -2],
[block_number, block_number, block_number]
]
# 현재 검사하는 위치의 블록이 하늘색 블록 첫 번째 케이스의 형태인지 확인한다.
for row in range(2):
for col in range(3):
if board[check_start_row + row][check_start_col - 1 + col] \
!= skyblue_first_block_with_black_blocks[row][col]:
return False
# 형태가 맞다면, 검은 블록을 포함하여 해당 블록을 모두 0으로 삭제한다.
for row in range(check_start_row, check_start_row + 2):
for col in range(check_start_col - 1, check_start_col - 1 + 3):
board[row][col] = 0
return True
# 현재 존재하고 검은 블록을 쌓을 수 있는 블록들의 위로 검은 블록을 2개씩 쌓는 함수.
def drop_black_blocks(N, board):
# 맨 왼쪽 열부터 맨 오른쪽 열까지 차례대로 실행
for col in range(N):
row = -1
while True:
# 맨 위의 행 부터 차례대로 한칸씩 내려온다.
# 블록을 만날 때 까지.
row += 1
# 만약 끝행까지 검사했으면 다음 열을 검사한다.
if row == N:
break
# 현재 검사하는 보드 위의 칸
checking_block = board[row][col]
# 검은블록의 값은 -2
# 만약 현재 검사하는 보드위가 검은블록이나 빈칸이라면 무시하고
# 한 칸 아래 행으로 내려간다.
if checking_block == 0 or checking_block == -2:
continue
# 만약 현재 검사하는 보드위가 어떤 블록으로 채워져있다면
if checking_block > 0:
# 그 블록 바로 위의 칸이 비어있으면 검은블록으로 채워준다.
if 0 <= row - 1 and board[row - 1][col] == 0:
board[row - 1][col] = -2
# 그 블록 바로 위 두 번째 칸이 비어있으면 검은블록으로 채워준다.
if 0 <= row - 2 and board[row - 2][col] == 0:
board[row - 2][col] = -2
# 제일 위에 있는 블록 위에 검은 블록 두 개를 떨어뜨렸으므로
# 다음 열에 작업하러 간다.
break
def solution(board):
# 총 삭제된 블록의 수
number_of_deleted_blocks = 0
# board 한 변의 길이
N = len(board)
# 맨 위의 행부터 맨 아래의 행까지 차례대로 검사
for row in range(N):
while True:
# 왼쪽에서 오른쪽으로 검사하기 때문에,
# B보다 왼쪽에서 먼저 탐지되는 A블록이
# B블록 아래에 있어서 원래는 삭제가 불가능했지만,
# B블록이 삭제되고 나서는 A블록이 삭제가 가능할 수도 있다.
# 따라서, 한 행에서 더이상 삭제가능한 블록이 안 나올 때 까지
# 해당 행의 삭제 과정을 반복한다.
# 이 행에서 새롭게 삭제된 블록의 수
number_of_new_deleted_blocks = 0
# 맨 왼쪽의 열부터 맨 오른쪽의 열까지 차례대로 검사
for col in range(N):
# 현재 존재하고, 검은 블록을 쌓을 수 있는 블록들의 위로 검은 블록을 2개씩 쌓는다.
# 어떤 블록을 삭제했을 때, 해당 블록이 차지하고 있던 자리에
# 검은 블록을 쌓을 수 있으므로
# 매 열을 검사할 때 마다 2개씩 쌓는다.
drop_black_blocks(N, board)
if board[row][col] > 0:
# 블록이 있다면
# 현재 검사하는 블록의 번호를 저장
block_number = board[row][col]
# 빨간색 블록의 세 번째 케이스이고 검은색 블록으로 채워져 있으면 검은색 블록과 함께 삭제
# 빨간색 블록의 네 번째 케이스이고 검은색 블록으로 채워져 있으면 검은색 블록과 함께 삭제
# 노란색 블록의 두 번째 케이스이고 검은색 블록으로 채워져 있으면 검은색 블록과 함께 삭제
# 노란색 블록의 세 번째 케이스이고 검은색 블록으로 채워져 있으면 검은색 블록과 함께 삭제
# 하늘색 블록의 첫 번째 케이스이고 이고 검은색 블록으로 채워져 있으면 검은색 블록과 함께 삭제
if red_third_case(row, col, board, block_number, N) \
or red_fourth_case(row, col, board, block_number, N) \
or yellow_second_case(row, col, board, block_number, N) \
or yellow_third_case(row, col, board, block_number, N) \
or skyblue_first_case(row, col, board, block_number, N):
# 어느 하나의 경우라도 해당돼서 삭제했다면
# 현재 이 행에서 새롭게 삭제한 블록의 수를 1 증가시키고,
number_of_new_deleted_blocks += 1
# 총 삭제한 블록의 수를 1 증가시킨다.
number_of_deleted_blocks += 1
# 만약 이 행에서 더이상 삭제된 블록이 없으면
# 다음 행으로 내려온다.
if number_of_new_deleted_blocks == 0:
break
# 총 삭제된 블록의 수를 반환한다.
return number_of_deleted_blocks
print(solution([
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 4, 0, 0, 0],
[0, 0, 0, 0, 0, 4, 4, 0, 0, 0],
[0, 0, 0, 0, 3, 0, 4, 0, 0, 0],
[0, 0, 0, 2, 3, 0, 0, 0, 5, 5],
[1, 2, 2, 2, 3, 3, 0, 0, 0, 5],
[1, 1, 1, 0, 0, 0, 0, 0, 0, 5]
]))
# 2
print(solution([
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 9, 0, 8, 0, 4, 0, 0, 0, 0],
[0, 7, 9, 8, 8, 8, 4, 0, 0, 0, 0],
[0, 7, 9, 9, 3, 4, 4, 0, 0, 0, 0],
[7, 7, 0, 2, 3, 0, 0, 0, 5, 5, 0],
[1, 2, 2, 2, 3, 3, 0, 0, 0, 5, 0],
[1, 1, 1, 6, 0, 0, 0, 0, 0, 5, 0],
[0, 0, 6, 6, 6, 0, 0, 0, 0, 0, 0]
]))
# 8
'Problem-solving > 프로그래머스' 카테고리의 다른 글
프로그래머스 - (2019 카카오 개발자 겨울 인턴십) 크레인 인형뽑기 게임 (Java) (0) | 2020.11.21 |
---|---|
프로그래머스 - (2018 KAKAO BLIND RECRUITMENT) [3차]자동완성 (Python3) (0) | 2020.09.03 |
프로그래머스 - (2019 KAKAO BLIND RECRUITMENT) 무지의 먹방 라이브 (Python3) (0) | 2020.09.01 |
프로그래머스 - (2020 카카오 인턴십) 동굴 탐험 (Python3) (0) | 2020.08.31 |
프로그래머스 - (2019 카카오 개발자 겨울 인턴십) 호텔 방 배정 (Python3) (0) | 2020.08.31 |
댓글