from collections import deque
N = int(input())
K = int(input())
applePos = [list(map(int, input().split())) for i in range(K)]
L = int(input())
dirInfo = [list(input().split()) for i in range(L)]
maps = [[False for i in range(N)] for j in range(N)]
# Termination 조건
def isGameOver():
x, y = snakePos[0]
snakeTemp = []
for i in range(1, len(snakePos)):
snakeTemp.append(snakePos[i])
# 벽에 부딪힘
if x < 0 or x >= N or y < 0 or y >= N:
return True
# 자신의 몸과 부딪힘
for itemX, itemY in snakeTemp:
if x == itemX and y == itemY:
return True
return False
def move():
global snakePos, curDir, terminate
headX, headY = snakePos.popleft()
updateX, updateY = headX, headY
temp = deque()
while snakePos:
temp.append(snakePos.popleft())
if curDir == "R":
snakePos.appendleft((headX, headY+1))
updateY = headY + 1
elif curDir == "L":
snakePos.appendleft((headX, headY - 1))
updateY = headY - 1
elif curDir == "U":
snakePos.appendleft((headX - 1, headY))
updateX = headX - 1
elif curDir == "D":
snakePos.appendleft((headX + 1, headY))
updateX = headX + 1
temp.appendleft((headX, headY))
if not checkApple(updateX, updateY):
if temp:
lastVal = temp.pop()
if lastVal == (updateX, updateY):
terminate = True
while temp:
snakePos.append(temp.popleft())
def checkApple(x, y):
if 0 <= x < N and 0 <= y < N and maps[x][y]:
maps[x][y] = False
return True
return False
def updateDir():
global curDir, dirCmd
if dirCmd != "-":
if curDir == "R":
if dirCmd == "L":
curDir = "U"
else:
curDir = "D"
elif curDir == "L":
if dirCmd == "L":
curDir = "D"
else:
curDir = "U"
elif curDir == "U":
if dirCmd == "L":
curDir = "L"
else:
curDir = "R"
elif curDir == "D":
if dirCmd == "L":
curDir = "R"
else:
curDir = "L"
index, timeCount = 0, 0
snakePos = deque()
curDir = "R"
dirCmd = "-"
terminate, isChecked = False, True
for idx, (itemRow, itemCol) in enumerate(applePos):
applePos[idx] = (itemRow-1, itemCol-1)
maps[itemRow-1][itemCol-1] = True
snakePos.append((0, 0))
while True:
timeCount += 1
move()
# 방향 전환
if isChecked and timeCount == int(dirInfo[index][0]):
dirCmd = dirInfo[index][1]
updateDir()
index += 1
if index >= len(dirInfo):
isChecked = False
if terminate or isGameOver():
break
print(timeCount)
구현 로직이 생각보다 복잡하지는 않았다. 하지만 두 가지 이유
로 풀이 시간이 엄청나게 걸려 버렸다.
첫번째는 문제의 조건과 입력이 1행 1열
부터 시작했고 그렇게 입력을 줬다는 점이다. 나는 당연하게도 0행 0열
부터로 생각하고 코드를 짰는데 입력이 1씩 커졌고 예외 처리도 그렇게 했으니 당연히 답이 틀릴 수 밖에 없다.
두번째는 위 문제보다 더 중요한 문제이다.
파이썬에서
for문 안
에 iterable 한 객체를순회할 때 쓰는 변수
도global 변수
와 이름이 중복되면 이게 생각치도 못하게 값이 바뀌면서 꼬여버린다.
함수 안에서의 local 변수
와 global 변수
만 구별해주면 되는 것으로 알았는데 반복문에서 순회용으로 쓰는 변수까지
신경 써야 한다는 사실은 정말 새로 알았다.
예를 들면 아래 코드와 같다.
idx = 0
for idx, (itemRow, itemCol) in enumerate(applePos):
... # 여기 반복문에서 `idx` 값이 계속 갱신되고 있음
...
if visited[idx]: # `idx`에 이상한 값이 들어가 있음
...