[PS] 기둥과 보 설치 (프로그래머스)
[코테]프로그래머스 - 기둥과 보 설치
프로그래머스 lv3_기둥과 보 설치 [2020 KAKAO BLIND RECUITEMENT 기출]
생각보다 하드 코딩하는 부분이 많았다.
완전 하드하게 짰을 때 고치는 과정에서 애먹어서 함수형태로 조금 리팩토링하였고,
그래도 테스트 케이스 반 정도가 오답이어서 질문하기를 참고했다.
가장 많이 도움 된 답변( https://programmers.co.kr/questions/15598 )을 보고 알 수 있었다.
내가 is_available_remove_row(y, x)
에서 row에 의존하는 기둥과 보의 존재를 조건을 주지않고 무조건 설치가 가능한지 체크를 했기 때문에 에러가 난 것.
해당 row를 지웠을 때 연관된 좌표들을 모두 설치가 가능하냐는 조건을 돌렸기에, 실제 map_
에는 연관이 없는 지점이어도 설치가 가능한지 체크해버리기 때문에 False
로 빠져나가는 경우가 꽤 있었던 것으로 보인다.
# 해답 확인..
# build_frame = [[x,y,a(기둥 보 여부),b(설치는 1, 삭제는 0)]... ]
def solution(n, build_frame):
answer = []
# 기둥은 1, 보는 2, 둘 다 설치 시 3으로 표현
map_ = [[0 for __ in range(n+4)] for _ in range(n+4)]
# 기둥 설치 가능한지
def is_available_install_column(ny,nx):
return ny == 2 or map_[ny-1][nx] in (1,3) or map_[ny][nx-1] in (2,3) or map_[ny][nx] in (2,3)
def is_available_install_row(ny, nx):
# 설치하고자 하는 좌표 밑에 기둥이 있을 때
if map_[ny-1][nx] in (1,3):
return True
# 설치하고자 하는 좌표 오른쪽 밑에 기둥이 있을 때
elif map_[ny-1][nx+1] in (1,3):
return True
# 양 옆에 보가 있을 때
elif map_[ny][nx-1] in (2,3) and map_[ny][nx+1] in (2,3):
return True
else:
return False
def is_available_remove_column(ny, nx):
# 기둥 윗부분(y+1, x)에 기둥이 있다면 그 부분에 대한 설치 조건을 체크한다.
if map_[ny+1][x] in (1, 3):
if not is_available_install_column(ny+1, nx):
return False
# 기둥 윗부분(y+1, x)에 보가 설치 되어 있다면 ..
if map_[ny+1][x] in (2,3):
if not is_available_install_row(ny+1, x):
return False
# 기둥 윗부분(y+1, x)에 보가 걸쳐 있다면((y+1, x-1)에 설치)
if map_[ny+1][x-1] in (2,3):
if not is_available_install_row(ny+1, x-1):
return False
return True
def is_available_remove_row(ny, nx):
# 보의 시작점(y, x)과 오른쪽에 (y, x+1) 대한 설치 조건 체크
# 시작점에 대해서는 기둥은 체크 안해도 될 듯
# 보를 지운 위치의 기둥 확인
if map_[ny][nx] in (1,3):
if not is_available_install_column(ny, nx):
return False
# 보를 지운 위치의 오른쪽 기둥 확인
if map_[ny][nx+1] in (1,3):
if not is_available_install_column(ny, nx+1):
return False
# 보를 지운 위치의 왼쪽 보 확인
if map_[ny][nx-1] in (2,3):
if not is_available_install_row(ny, nx-1):
return False
# 보를 지운 위치의 오른쪽 보 확인
if map_[ny][nx+1] in (2,3):
if not is_available_install_row(ny, nx+1):
return False
return True
# 기둥은 0, 보는 1로 나타냄
for condition in build_frame:
x,y,a,b = condition
y += 2
x += 2
''' 아웃 오브 인덱스 에러 처리는 이후에 생각하자 '''
# 설치의 경우
if b == 1:
# 기둥 설치 시 설치하고자 하는 좌표 (y, x) 기준으로,
if a == 0:
# (y-1, x)에 기둥이 설치되어 있거나, (y, x-1) or (y, x)에 보가 설치되어 있어야 한다.
# (아니면 땅이거나 (y == 0))
if is_available_install_column(y,x):
map_[y][x] += 1
answer.append([x-2,y-2,a])
# 보 설치 시 설치하고자 하는 좌표 (y, x) 기준으로,
elif a == 1:
# (y-1, x) or (y-1, x+1)에 기둥이 설치되어 있거나, (y, x-1) and (y, x+1)에 보가 설치되어 있어야 한다.
if is_available_install_row(y,x):
map_[y][x] += 2
answer.append([x-2,y-2,a])
# 삭제의 경우
if b == 0:
if [x-2,y-2,a] not in answer:
continue
# 기둥 삭제 시 (y, x)
if a == 0:
# 우선 삭제해본다.
map_[y][x] -= 1
# 기둥 윗부분(y+1, x)에 기둥이 있다면 그 부분에 대한 설치 조건을 체크한다.
if is_available_remove_column(y,x):
answer.remove([x-2,y-2,a])
# 만약 설치 조건에 어긋난다면, 삭제를 시행하지 않음 #
else:
map_[y][x] += 1
# 보 삭제 시 (y, x)
if a == 1:
map_[y][x] -= 2
# 보의 시작점(y, x)과 오른쪽에 (y, x+1) 대한 설치 조건 체크
# 시작점에 대해서는 기둥은 체크 안해도 될 듯
if is_available_remove_row(y,x):
answer.remove([x-2,y-2,a])
else:
# 설치 조건에 어긋나면, 삭제 시행하지 않음
map_[y][x] += 2
answer.sort(key=lambda k:(k[0], k[1], k[2]))
return answer