이 문제를 푸는데 1시간 반이나 걸렸지만 한 큐에 통과했다!!😭🎉
이 문제는구현
문제며 2x2를 터트리는 기능
과 터트려진 block에 위에서부터 끌어오는 기능
으로 접근하였다.
터트린 것: ''(빈 문자열)로 표시
set
에 넣어준다. ''빈문자열
로 값을 대체한다.과정 1-2
에서 set을 쓴 이유는 아래와 같다.
set에 넣어준 이유는 탐색하면서 빈 배열로 만들어 블록을 터트릴 수 있지만 board[row][col] = ''이 되면 탐색을 제대로 하지 못하기 때문이다.`문제 설명에 라이온이 겹치는 경우
code
def pang_blocks(m, n, board):
removed_block_set = set()
dxs = [0, 1, 1]
dys = [1, 1, 0]
for row in range(m - 1):
for col in range(n - 1):
if board[row][col] != '':
count = 1
for dx, dy in zip(dxs, dys):
next_x, next_y = row + dx, col + dy
if board[row][col] == board[next_x][next_y]:
count += 1
if count == 4:
removed_block_set.add((row, col))
removed_block_set.update([(row + dx, col + dy) for dx, dy in zip(dxs, dys)])
# fill with empty string where the block removed!
for row, col in removed_block_set:
board[row][col] = ''
return len(removed_block_set), board
이 부분에서 많은 시간이 걸렸는데 결국은 해결했다!!!
아래에 대략적인 로직만 적어놓고 이는 글보단 그림을 첨부하면 좋을 것 같아서 이해를 도와줄 수 있는 그림을 로직 아래 첨부했다.
''빈 문자열
로 대체code
def drop_blocks(m, n, board):
for col in range(n):
for row in range(m):
if board[row][col] == '':
for prev_row in range(row - 1, -1, -1):
board[prev_row + 1][col] = board[prev_row][col]
board[prev_row][col] = ''
return board
import copy
def pang_blocks(m, n, board):
removed_block_set = set()
dxs = [0, 1, 1]
dys = [1, 1, 0]
for row in range(m - 1):
for col in range(n - 1):
if board[row][col] != '':
count = 1
for dx, dy in zip(dxs, dys):
next_x, next_y = row + dx, col + dy
if board[row][col] == board[next_x][next_y]:
count += 1
if count == 4:
removed_block_set.add((row, col))
removed_block_set.update([(row + dx, col + dy) for dx, dy in zip(dxs, dys)])
# fill with empty string where the block removed!
for row, col in removed_block_set:
board[row][col] = ''
return len(removed_block_set), board
def drop_blocks(m, n, board):
for col in range(n):
for row in range(m):
if board[row][col] == '':
for prev_row in range(row - 1, -1, -1):
board[prev_row + 1][col] = board[prev_row][col]
board[prev_row][col] = ''
return board
def solution(m, n, board):
answer = 0
copy_board = copy.deepcopy(list(map(list, board)))
while True:
count_removed_blocks, next_board = pang_blocks(m, n, copy_board)
if count_removed_blocks == 0:
break
answer += count_removed_blocks
dropped_board = drop_blocks(m, n, next_board)
return answer
이 풀이를 봤을 때 위의 값을 아래로 끌어오는 것이 직관적으로 눈에 잘 들어왔다.
def solution(m, n, board):
answer = 0
board = list(map(list, board))
while True:
visited = [[0] * n for _ in range(m)]
for i in range(m - 1):
for j in range(n - 1):
k = board[i][j]
if k != 0:
if board[i][j + 1] == k and board[i + 1][j] == k and board[i + 1][j + 1] == k:
visited[i][j], visited[i + 1][j], visited[i][j + 1], visited[i + 1][j + 1] = 1, 1, 1, 1
cnt = 0
for i in range(m):
cnt += sum(visited[i])
if not cnt:
break
answer += cnt
for i in range(m - 1, -1, -1):
for j in range(n):
if visited[i][j]:
x = i - 1
while x >= 0 and visited[x][j] == 1:
x -= 1
if x < 0:
board[i][j] = 0
else:
board[i][j] = board[x][j]
visited[x][j] = 1
return answer
이 풀이는 board를 재배열하는 것만 가져온 것으로 프로그래머스에서 통과한 사람들만 볼 수 있는 다른 사람풀이에서 가져왔다.
개인적으로 되게 신박해서 감탄했다. 문자열로 처리를 했으며 블록이 터진 곳을 '0'으로 처리하고
'0'의 공간을 없앤뒤에 row의 윗부분부터 zfill
로 0으로 채움으로써 위의 블록을 빈 블록까지 끌어내렸다.
def restruct(m, n, board):
re_board = [''] * m
for col in range(n):
ys = ''.join([board[row][col] for row in range(m)]).replace('0','').zfill(m)
for row in range(m):
re_board[row] += ys[row]
return re_board
다른사람 풀이를 보고 느낀 것이 많다.
첫 번째로는 난 set
을 이용하여 위치정보를 count한 것을 answer에 더했는데 다른사람풀이에서는 visited(방문 보다는 터진 위치이므로 mark_empty_block이 더 나을 것 같다)
를 이용해서 터진 위치를 1로 체크
하고 1의 개수를 새서 answer에 더했다.
두 번째는 아예 문자열과 replace, zfill을 이용하여 옮기는 효과를 구현해낸 것에 감탄했다.
블로깅을 시작한지 얼마 안 됐지만, 처음에 프로그래머스에서 코딩 연습문제를 풀이하면서 다른 사람 코드들은 거의 안 봤는데 요새 보면서 많은 것을 느낀다. 더 많이 참고하고 배울 점을 찾아나가야겠다.