백트래킹·구현
시뮬레이션
시키는 대로 그대로 하기
로봇에게 명령 줄이 주어졌습니다. 다 하고 나면 처음 칸에서 몇 칸 떨어질지 먼저 고르고, 명령을 한 글자씩 대신 실행해 보세요.
방에 로봇(▲)이 서 있어요. 명령 줄을 한 글자씩 따라 해요. F 는 앞으로 한 칸 가고, R 은 오른쪽으로, L 은 왼쪽으로 90도 돌아요. 명령 8개를 다 하고 나면 로봇은 처음 칸에서 몇 칸 떨어져 있을까요?
FFRFFLFF
내 예상 칸 · 실제 4칸 → 달랐어요
(3, 0) → (2, 0) → (1, 0) → (1, 1) → (0, 1)명령 8개 중 F 2번은 막혀서 제자리였습니다. 막히지 않았다면 6칸 떨어진 곳에 섰을 텐데, 실제로는 4칸입니다.
- 한 글자씩 그대로 — 명령이 시키는 일을 규칙대로 하나씩 따라 했다
- 막히면 — 앞 칸이 벽이든 방 바깥이든 로봇은 제자리에 섰다
- 돌기는 — 칸은 그대로고 방향만 바뀌었다
규칙을 한 단계씩 그대로 따라 하며 결과를 구하는 방법 = 시뮬레이션(simulation)
방향 네 개를 숫자 두 줄(dr, dc)로 두면 앞 칸은 r + dr[d], 돌기는 d = (d + 1) % 4 한 줄입니다. 이 숫자 두 줄 = 델타 배열
앞 칸이 막혔는지는 움직이기 전에 본다
- 방금 겪은 막힘 — 5번째 명령은 벽에, 8번째 명령은 방 바깥에 막혔다. 둘 다 제자리였다
- 순서 — 앞 칸을 먼저 계산하고, 갈 수 있는 칸인지 보고, 그다음에 움직인다
- 움직인 뒤에 보면 — 로봇이 벽 안에 들어가 있다. 벽은 지나갈 수 없다
코드는 규칙을 한 줄씩 그대로 옮긴 것이다
위에서 한 것과 같은 방, 같은 명령입니다. (r, c) 는 위에서 r번째 줄, 왼쪽에서 c번째 칸이고 0부터 셉니다. d 는 방향이고 0 위, 1 오른쪽, 2 아래, 3 왼쪽입니다.
다음을 눌러 한 줄씩 넘기며 명령 줄과 로봇을 보세요.
FFRFFLFF
로봇 (3, 0) 칸 · ▲ 위를 봄
다음을 눌러 한 줄씩 넘겨 보세요
r = 3 c = 0 d = 0
- 1def robot(commands, grid, r, c):
- 2 rows, cols = len(grid), len(grid[0])
- 3 dr = [-1, 0, 1, 0]
- 4 dc = [0, 1, 0, -1]
- 5 d = 0
- 6 for cmd in commands:
- 7 if cmd == "F":
- 8 nr, nc = r + dr[d], c + dc[d]
- 9 if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] == 0:
- 10 r, c = nr, nc
- 11 elif cmd == "R":
- 12 d = (d + 1) % 4
- 13 else:
- 14 d = (d - 1) % 4
- 15 return r, c
dr·dc— d 방향으로 한 칸 갈 때 행·열이 얼마나 바뀌는지. 위(0)는 행이 −1이다0 <= nr < rows …— 앞 칸이 방 안이고 빈 칸일 때만 참이다. 거짓이면 10번 줄을 건너뛴다d = (d + 1) % 4— 오른쪽으로 돌기. 3 다음은 다시 0이 된다
명령 F F R F F L F F 에서 가운데 L 을 R 로 바꾸면 로봇은 어느 칸에 설까요?
시뮬레이션에서 틀리는 자리
- (행, 열)과 (x, y)를 섞는다 — 위로 가면 행이 줄어든다(
dr[0] = -1). x, y 로 생각하면 위아래가 뒤집힌다 - 경계 검사를 빼면 — 위·왼쪽 바깥은 에러 없이
grid[-1]로 반대편 줄을 읽는다. 이 방에서 (0, 1) 대신 (-1, 1) 에 섰다. 오른쪽·아래 바깥은IndexError: list index out of range가 난다 - 방향 순서를 문제와 맞춘다 — 위, 오른쪽, 아래, 왼쪽이 시계 방향이다. 왼쪽과 오른쪽 자리를 바꾸면 같은 명령이 (0, 0) 에서 끝났다
(d - 1) % 4는 — 파이썬은 3이 나온다. 다른 언어는 -1 이 나온다. 그래서(d + 3) % 4로 쓰기도 한다[[0] * 5] * 5로 방을 만들면 — 행이 전부 같은 리스트다. 한 칸에 벽을 세우면 모든 줄의 같은 열이 벽이 된다.[[0] * 5 for _ in range(5)]로 만든다
문제에서 이 말이 보이면
다음 장에서는 뒤집어도 같은 말인지 확인하는 문자열과 회문을 봅니다.