미로 탈출 명령어 문서의 문제 1 풀이 코드다. if __name__ == "__main__": 아래가 자체 테스트다.

"""미로 탈출 명령어 (프로그래머스 150365) 풀이와 검증."""
import random
from itertools import product

MOVES = [("d", 1, 0), ("l", 0, -1), ("r", 0, 1), ("u", -1, 0)]      # 사전 순


def solution(n, m, x, y, r, c, k):
    dist = abs(x - r) + abs(y - c)
    if dist > k or (k - dist) % 2 == 1:
        return "impossible"
    path = []
    for step in range(k):
        remain = k - step - 1                # 이번 걸음 뒤에 남는 걸음 수
        for ch, dx, dy in MOVES:
            nx, ny = x + dx, y + dy
            if 1 <= nx <= n and 1 <= ny <= m and abs(nx - r) + abs(ny - c) <= remain:
                x, y = nx, ny
                path.append(ch)
                break
    return "".join(path)


def trace(n, m, x, y, r, c, k):
    rows = []
    for step in range(k):
        remain = k - step - 1
        tried = []
        for ch, dx, dy in MOVES:
            nx, ny = x + dx, y + dy
            if not (1 <= nx <= n and 1 <= ny <= m):
                tried.append((ch, "밖"))
                continue
            d = abs(nx - r) + abs(ny - c)
            tried.append((ch, d))
            if d <= remain:
                x, y = nx, ny
                break
        rows.append((remain, tried, (x, y)))
    return rows


def by_all_strings(n, m, x, y, r, c, k):
    """길이 k 문자열을 사전 순으로 모두 만들어, 처음으로 규칙에 맞는 것을 돌려준다."""
    step = {ch: (dx, dy) for ch, dx, dy in MOVES}
    for s in product("dlru", repeat=k):
        px, py, good = x, y, True
        for ch in s:
            px, py = px + step[ch][0], py + step[ch][1]
            if not (1 <= px <= n and 1 <= py <= m):
                good = False
                break
        if good and (px, py) == (r, c):
            return "".join(s)
    return "impossible"


if __name__ == "__main__":
    assert solution(3, 4, 2, 3, 3, 1, 5) == "dllrl"
    assert solution(2, 2, 1, 1, 2, 2, 2) == "dr"
    assert solution(3, 3, 1, 2, 3, 3, 4) == "impossible"
    # 6단계 추적
    assert trace(3, 4, 2, 3, 3, 1, 5) == [
        (4, [("d", 2)], (3, 3)),
        (3, [("d", "밖"), ("l", 1)], (3, 2)),
        (2, [("d", "밖"), ("l", 0)], (3, 1)),
        (1, [("d", "밖"), ("l", "밖"), ("r", 1)], (3, 2)),
        (0, [("d", "밖"), ("l", 0)], (3, 1)),
    ]
    # 무작위 비교: 모든 문자열을 사전 순으로 보는 풀이
    rng = random.Random(150365)
    for _ in range(1500):
        n, m = rng.randint(2, 4), rng.randint(2, 4)
        x, y = rng.randint(1, n), rng.randint(1, m)
        r, c = rng.randint(1, n), rng.randint(1, m)
        if (x, y) == (r, c):
            continue
        k = rng.randint(1, 7)
        assert solution(n, m, x, y, r, c, k) == by_all_strings(n, m, x, y, r, c, k), (n, m, x, y, r, c, k)
    # 가장 큰 입력
    assert len(solution(50, 50, 1, 1, 50, 50, 2500)) == 2500
    assert 4 ** 2500 > 10 ** 1500
    print("ALL CHECKS PASSED")