# Problem Description
This is a matrix traversal problem where:
- We navigate through a matrix containing directional characters (R, L, U, D)
- Movement starts from a given coordinate and follows the directional instructions
- The goal is to find the final coordinates where the path exits the matrix
- The coordinates are 1-indexed (as shown in the examples), the coordinates are (row, column)
- There are special rules governing direction changes and path termination

# Visual Facts
1. Matrix Structure:
   - First example show a 3x3 matrix, the second example shows a 3x4 matrix
   - Contains only directional characters: R (right), L (left), U (up), D (down)
   - Uses 1-based indexing for both rows and columns

2. Path Visualization:
   - Green dot marks START position
   - Red arrow marks END position
   - Orange arrows show the path of movement
   - Purple arrows point to an important rule note

3. Start/End Markers:
   - Example 1: Starts at (1,1), 
     - the letter at row 1 col 1 is R, so we move right to (1,2)
     - the letter at row 1 col 2 is D, so we move down to (2,2)
     - the letter at row 2 col 2 is L, so we move left to (2,1)
     - the letter at row 2 col 1 is R, so we move right to (2,2)
     - (2, 2) has been visited, so direction remains right
     - now we move right to (2,3), containing a letter U, so then up to (1,3), 
     - the letter at (1,3) is U, since we can't move up, we exit at (1,3)
   - Example 2: Starts at (1,2), ends at (3,1)
     - follow the path as per the directional letters in the matrix

# Visual Patterns
1. Movement Rules:
   - Each cell's letter determines the direction when leaving that cell

2. Critical Constraints:
   - "Each block can only change direction once" (explicitly stated)
   - When revisiting a cell, its direction instruction is ignored (continue in current direction)

3. Path Termination:
   - The path ends when it would move outside the matrix boundaries
   - The last valid position before exiting becomes the end coordinates

4. Direction Change Pattern:
   - First visit to a cell: Apply the direction indicated by the letter
   - Subsequent visits: change directions based on the letter of the following cell
   - This creates a deterministic path through the matrix

5. Traversal Pattern:
   - The path can intersect with itself, but there is no loop because each cell can change direction only once
   - The solution always reaches an exit point (no infinite loops)
   - Movement is continuous until reaching a matrix boundary


# Solution
from typing import List, Tuple

def move_direction(x: int, y: int, direction: str) -> Tuple[int, int]:
    """Move to the next cell based on the given direction."""
    if direction == 'L':
        return x, y - 1
    elif direction == 'R':
        return x, y + 1
    elif direction == 'U':
        return x - 1, y
    elif direction == 'D':
        return x + 1, y
    return x, y


def escape_path(matrix: List[List[str]], start_x: int, start_y: int) -> int:
    """Simulate the escape from a given start position."""
    n = len(matrix)
    m = len(matrix[0])
    visited = set()
    x, y = start_x, start_y
    x_, y_ = x, y

    while 1 <= x <= n and 1 <= y <= m:
        end_point = (x, y)
        if (x, y) in visited:
            x, y = move_direction(x, y, direction=matrix[x_-1][y_-1])
            continue
        visited.add((x, y))
        x_, y_ = x, y
        x, y = move_direction(x, y, matrix[x-1][y-1])

    return end_point


def solution(matrix: List[List[str]], start: Tuple[int, int]) -> Tuple[int, int]:
    """
    Given the starting coordinates, find the ending coordinates in a 2D matrix.

    Args:
        matrix (List[List[str]]): A 2D matrix where each element is one of four upper case characters
        start (Tuple[int, int]): The starting position as (row, col) coordinates (1-indexed)

    Returns:
        Tuple[int, int]: The ending position as (row, col) coordinates (1-indexed)
    """
    return escape_path(matrix, start[0], start[1])



# Test Script
def test():
    test_cases = [
        (
            [['R', 'D', 'L'],
             ['L', 'U', 'R'],
             ['U', 'L', 'U']],
            (2, 2),
            (2, 1)
        ),
        (
            [['D', 'R', 'L', 'D'],
             ['U', 'L', 'U', 'L'],
             ['D', 'U', 'U', 'R'],
             ['R', 'D', 'D', 'L']],
            (3, 3),
            (4, 2)
        ),
        (
            [['D', 'R', 'D', 'D'],
             ['L', 'U', 'R', 'U']],
            (2, 2),
            (2, 4)
        ),
        (
            [['R', 'D', 'R', 'U', 'D'],
             ['U', 'L', 'U', 'L', 'U'],
             ['D', 'U', 'U', 'R', 'R']],
            (1, 2),
            (1, 4)
        ),
        (
            [['D', 'R', 'D', 'U'],
             ['U', 'U', 'R', 'L'],
             ['L', 'D', 'R', 'U']],
            (2, 2),
            (3, 1)
        )
    ]

    for i, (matrix, start, expected_output) in enumerate(test_cases):
        try:
            output = solution(matrix, start)
        except Exception as e:
            error_message = (
                f"An exception occurred while running test case {i + 1}:\n"
                f"`matrix`:\n"
                f"{'\n'.join([str(row) for row in matrix])}\n"
                f"`start`: {start}\n\n"
                f"Exception: '{str(e)}'"
            )
            assert False, error_message

        if output != expected_output:
            error_message = (
                f"The following Test Case {i + 1} failed:\n"
                f"`matrix`:\n"
                f"{'\n'.join([str(row) for row in matrix])}\n"
                f"`start`: {start}\n\n"
                f"Actual Output: {output}\n"
                f"Expected Output: {expected_output}"
            )
            assert False, error_message

test()