좌표를 헷갈리지 말 것!! (#14499 주사위 굴리기)
#14499 주사위 굴리기 https://www.acmicpc.net/problem/14499
14499번: 주사위 굴리기
첫째 줄에 지도의 세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x, y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1), 그리고 명령의 개수 K (1 ≤ K ≤ 1,000)가 주어진다. 둘째 줄부터 N개의 줄에 지
www.acmicpc.net
일단 주사위를 구현하는 것 부터가 빡셌다.
처음엔 리스트 두개로 구현하려고 했는데 리스트 간에 값을 교환하는 횟수가 너무 많을 것 같다는 생각이 들었다.
주사위가 동서남북으로 움직일 때마다 각 6면의 변화를 상상했다.
이렇게 변화하는 모습을 보였다.
(사실 처음에 잘못 판단해서 삽질을 좀 했다.)
따라서 주사위 구현은 정수형 자료형을 저장하는 6개 변수로 진행했다.
각 면의 방향에 따라 6개의 변수를 생성하고 주사위의 움직임을 추적한다.
그리고 제출했는데,
자꾸 시작도 못해보고 1%에서 틀린다.
그래서 이유를 찾아봤는데,,,,
지도에서 좌표를 표기하는 형태에서 오류가 있었다.
대부분이 그렇겠지만, 나는 지도를 표현할 때 2차원 리스트를 사용한다.
그리고 문제는 인덱싱인데, 2차원 리스트에 대한 인덱싱은 maps[a][b]로 진행된다.
이렇게 진행하면 다음과 같은 형태로 리스트에 접근하게 된다.
쉽게 표현하면, a가 세로축이 되고, b가 가로축이 된다.
나는 변수를 선언할 때 가로축 세로축을 각각 x, y로 표현한다.
따라서 파이썬 리스트 인덱싱을 진행할 때에는 다음과 같이 진행해야한다.
maps[y][x]
수학공부를 할 때 (x, y)라고 쓰는게 습관이 되어 있어서 헷갈리기 쉽다.
절대 헷갈리지 말자 절대!!
라며 매일 매일 다짐했다.
하지만.... 이번엔 새로운 이슈가 있었다.
입력을 받을 때 이렇게 받아버린 것이다.
하지만 실제 입력은 (나의 기준에서는) y, x순으로 들어오고 있었다.
하지만 테스트케이스는 모두 0,0에서 출발하는 경우였고 여기서 체크되지 않은 나의 실수는 실제 채점 시 1%에서 틀리는 참사로 이어진 것이다.
하.....
그렇게 완성된 나의 정답코드!
# get input
h, w, y, x, k = map(int, input().split())
# 지도의 각 칸에는 정수가 하나씩 쓰여져 있다.
maps = [[int(x) for x in input().split()] for _ in range(h)]
# 동 : 1, 서 : 2, 북 : 3, 남 : 4
cmds = [int(x) for x in input().split()]
# 가장 처음 주사위의 모든 면에 0이 적혀져 있다.
top = bott = nort = sout = west = east = 0
def valid_pos(x, y): # 지도의 바깥인 경우
global h, w
# print(x, y)
return (0 <= x < w) and (0 <= y < h)
while len(cmds):
cmd = cmds.pop(0)
if cmd == 1: # move East
nx, ny = x + 1, y
if not valid_pos(nx, ny): # 지도의 바깥인 경우 명령 무시
continue
x, y = nx, ny
tmp = east
top, west, east = west, bott, top
# 0이 아닌 경우에는 칸에 쓰여있는 수가 주사위의 바닥면으로 복사되며 칸의 수는 0이 된다.
if maps[y][x]:
bott = maps[y][x]
maps[y][x] = 0
# 이동한 칸에 쓰여있는 수가 0이면, 주사위의 바닥면에 쓰여 있는 수가 칸에 복사된다.
else:
bott = tmp
maps[y][x] = bott
elif cmd == 2: # move west
nx, ny = x - 1, y
if not valid_pos(nx, ny):
continue
x, y = nx, ny
tmp = west
top, west, east = east, top, bott
if maps[y][x]:
bott = maps[y][x]
maps[y][x] = 0
else: # 이동한 칸에 쓰여있는 수가 0이면, 주사위의 바닥면에 쓰여 있는 수가 칸에 복사된다.
bott = tmp
maps[y][x] = bott
elif cmd == 3: # move north
nx, ny = x, y - 1
if not valid_pos(nx, ny):
continue
x, y = nx, ny
tmp = nort
top, nort, sout = sout, top, bott
if maps[y][x]:
bott = maps[y][x]
maps[y][x] = 0
else: # 이동한 칸에 쓰여있는 수가 0이면, 주사위의 바닥면에 쓰여 있는 수가 칸에 복사된다.
bott = tmp
maps[y][x] = bott
elif cmd == 4: # move south
nx, ny = x, y + 1
if not valid_pos(nx, ny):
continue
x, y = nx, ny
tmp = sout
top, nort, sout = nort, bott, top
if maps[y][x]:
bott = maps[y][x]
maps[y][x] = 0
else: # 이동한 칸에 쓰여있는 수가 0이면, 주사위의 바닥면에 쓰여 있는 수가 칸에 복사된다.
bott = tmp
maps[y][x] = bott
print(top)
# print("cmd : ", cmd)
# print(top, bott, nort, sout, west, east)
# for m in maps:
# print(m)
틀릴 때 마다 검토하는건 굉장히 번거로우니
빡센 구현의 경우에는 문제에 나와있는 조건들을 주석으로 작성하면서 진행하는게 좋(았)다.
그럼 이만.
나의 알고리즘 문제풀이 Rule #1 : 지도 표현하기
지도는 2차원 리스트로 표현하고, position은 x, y로 표현한다.
따라서 접근 방법은 maps[y][x]로 설정한다. x와 y의 순서를 혼동하지 말자.
수학공부를 할 때 (x, y)라고 쓰는게 습관이 되어 있어서 헷갈리기 쉽다.
절대 헷갈리지 말자 절대!!