✅문제 설명
다음 그림과 같이 지뢰가 있는 지역과 지뢰에 인접한 위, 아래, 좌, 우 대각선 칸을 모두 위험지역으로 분류합니다.
지뢰는 2차원 배열 board에 1로 표시되어 있고 board에는 지뢰가 매설 된 지역 1과, 지뢰가 없는 지역 0만 존재합니다.
지뢰가 매설된 지역의 지도 board가 매개변수로 주어질 때, 안전한 지역의 칸 수를 return하도록 solution 함수를 완성해주세요.✅제한사항
board는 n * n 배열입니다.
1 ≤ n ≤ 100
지뢰는 1로 표시되어 있습니다.
board에는 지뢰가 있는 지역 1과 지뢰가 없는 지역 0만 존재합니다.
def solution(board):
answer = 0
for i in range(len(board)) :
for j in range(len(board)) :
if board[i][j] == 1 :
if 0<i<len(board)-1 and 0<j<len(board)-1:
board[i][j-1]=2 if board[i][j-1] == 0 else board[i][j-1]
board[i][j+1]=2 if board[i][j+1] == 0 else board[i][j+1]
board[i-1][j]=2 if board[i-1][j] == 0 else board[i-1][j]
board[i+1][j]=2 if board[i+1][j] == 0 else board[i+1][j]
board[i-1][j-1]=3 if board[i-1][j-1] == 0 else board[i-1][j-1]
board[i-1][j+1]=3 if board[i-1][j+1] == 0 else board[i-1][j+1]
board[i+1][j+1]=3 if board[i+1][j+1] == 0 else board[i+1][j+1]
board[i+1][j-1]=3 if board[i+1][j-1] == 0 else board[i+1][j-1]
for i in range(len(board)) :
for j in range(len(board)) :
if board[i][j] == 0:
answer += 1
print(board)
return answer
if board[i][j] == 1 :
i와 j가 인덱스에서 벗어나지 않게 하기 위해
0<i<len(board)-1 and 0<j<len(board)-1
이 조건을 사용해서 (0, 0) 에 지뢰가 있는 경우의 위험지역을 세지 못했다.
위의 오류를 수정한 두번째 코드이다.
def solution(board):
answer = []
for i in range(len(board)) :
for j in range(len(board)) :
if board[i][j] == 1 :
answer.append([i, j])
answer.append([i, j+1])
answer.append([i, j-1])
answer.append([i-1, j])
answer.append([i+1, j])
answer.append([i+1, j+1])
answer.append([i-1, j-1])
answer.append([i+1, j-1])
answer.append([i-1, j+1])
print(len(answer))
answer = [i for i in set(answer) if 0<i[0]<len(board[0]) and 0<i[1]<len(board[1])]
print(answer)
return len(board)**2 - len(answer)
지뢰가 있는 좌표의 위, 아래, 좌우, 그리고 대각선의 모든 좌표를 answer 배열에 추가하고, 인덱스 범위가 아닌 것은 나중에 제외시키는 방법이다.
위 코드를 실행시키니까 다음과 같은 오류가 발생했다.
TypeError: unhashable type: 'list'
위 오류는 answer의 원소가 list이기 때문이다. set()에 들어있는 값은 해쉬가 가능해야 한다. 즉, 문자열, 숫자, 튜플만을 인자로 받을 수 있다.
def solution(board):
answer = []
for i in range(len(board)) :
for j in range(len(board)) :
if board[i][j] == 1 :
answer.append((i, j))
answer.append((i, j+1))
answer.append((i, j-1))
answer.append((i-1, j))
answer.append((i+1, j))
answer.append((i+1, j+1))
answer.append((i-1, j-1))
answer.append((i+1, j-1))
answer.append((i-1, j+1))
answer = [i for i in set(answer) if 0<=i[0]<len(board[0]) and 0<=i[1]<len(board[1])]
return len(board)**2 - len(answer)
위 오류를 해결하기 위해 answer.append([i, j])
를 answer.append((i, j))
로 수정했더니 테스트 케이스 9번빼고 통과되었다.
테스트 케이스 9번은 런타임 오류가 났다. 런타임 오류를 해결하기 위해
answer = [i for i in set(answer) if 0<=i[0]<len(board[0]) and 0<=i[1]<len(board[1])]
위 코드를
answer = [i for i in set(answer) if 0<=i[0]<len(board) and 0<=i[1]<len(board)]
위와 같이 수정하였다.
def solution(board):
answer = 0
for col in range(len(board)):
for row in range(len(board[col])):
if board[row][col] == 1:
for j in range(max(col-1,0),min(col+2,len(board))):
for i in range(max(row-1,0),min(row+2,len(board))):
if board[i][j] == 1:
continue
board[i][j] = -1
for i in board:
answer += i.count(0)
return answer
max와 min으로 범위를 벗어나지 않게 해줬다.
1. 지뢰에 해당하는 ( i , j ) 좌표를 만나면 i-1부터 i+1 그리고 j-1부터 j+1의 모든 조합이 위험지역이므로 해당 좌표들의 값을 1로 바꿔준다.
1-1. 단, i-1, j-1의 값이 0보다 작아지는 경우와 i+1, j+1의 값이 마지막 인덱스를 넘어가는 경우를 min과 max 함수를 사용하여 처리했다.
2. 짧은 코드
def solution(board):
n = len(board)
danger = set()
for i, row in enumerate(board):
for j, x in enumerate(row):
if not x:
continue
danger.update((i+di, j+dj) for di in [-1,0,1] for dj in [-1, 0, 1])
return n*n - sum(0 <= i < n and 0 <= j < n for i, j in danger)
if not x:
코드를 사용하여 x가 0이면 그냥 지나가도록 했다.danger.update((i+di, j+dj) for di in [-1,0,1] for dj in [-1, 0, 1])
set()에 들어있는 값은 해쉬가 가능해야 한다.
즉, set() 함수는 인자로 문자열, 숫자, 튜플만을 받을 수 있다.
배열의 인덱스를 이용해 문제를 풀 때, min(), max() 함수를 활용해 예외처리를 하는 것도 한가지 방법이다.