# Problem Description
This problem involves navigating through a matrix where each cell contains a directional character ('R', 'L', 'U', 'D'). Starting from a given coordinate, the goal is to determine if it's possible to reach a specified home position by following the directional instructions. Each cell can change direction only once, and the coordinates are 1-indexed.

# Visual Facts
1. **Matrix Structure**:
   - The matrix contains directional characters: 'R' (right), 'L' (left), 'U' (up), 'D' (down).
   - The matrix uses 1-based indexing for both rows and columns.
   - Example 1: 3x3 matrix.
   - Example 2: 3x4 matrix.

2. **Start/End Markers**:
   - Example 1: Starts at (1,1), ends at (0,2).
   - Example 2: Starts at (1,2), ends at (3,5).

3. **Home Location**:
   - The home is located outside the boundaries of the matrix, so the coordinates will extend beyond the matrix range.
   - The row of the home could be 0 or len(matrix) + 1 (1-indexed).
   - The column of the home could be 0 or len(matrix[0]) + 1 (1-indexed).

3. **Path Visualization**:
   - Green dot marks the START position.
   - Black house symbol marks the HOME position.
   - Orange arrows show the path of movement.
   - Purple arrow points to an important rule note: "Each block can only change direction once."

# Visual Patterns
1. **Movement Rules**:
   - Each cell's letter determines the direction when leaving that cell.
   - The path follows the direction indicated by the letter in the current cell.

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

3. **Path Termination**:
   - The path ends when it would move outside the matrix boundaries.
   - If the path reaches the home position when it leaves the matrix boundaries, return True; otherwise, return False.

4. **Direction Change Pattern**:
   - First visit to a cell: Apply the direction indicated by the letter.
   - Subsequent visits: Continue in the current direction without changing based on the cell's letter.
   - 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 solution(matrix: List[List[str]], start: Tuple[int, int], home: Tuple[int, int]) -> bool:
    """
    Determine if it's possible to reach home given the starting point and the house coordinates.

    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)
        home (Tuple[int, int]): The home position as (row, col) coordinates (1-indexed)
    
    Output:
        Return True if it's possible to reach home, otherwise False
    """
    # Convert 1-indexed positions to 0-indexed for easier handling in Python lists
    start = (start[0] - 1, start[1] - 1)
    home = (home[0] - 1, home[1] - 1)
    
    n, m = len(matrix), len(matrix[0])
    
    # Direction vectors for 'R', 'L', 'U', 'D'
    directions = {
        'R': (0, 1),
        'L': (0, -1),
        'U': (-1, 0),
        'D': (1, 0)
    }
    
    # Function to check if a position is out of bounds
    def out_of_bounds(r, c):
        return r < 0 or r >= n or c < 0 or c >= m
    
    # Starting from the initial position
    r, c = start
    visited = set()
    # print(home)
    while True:
        # Check if the current position is the home position
        if (r, c) == home:
            return True
        
        # If the position is out of bounds, check if it's the home position
        if out_of_bounds(r, c):
            if (r, c) == home:
                return True
            else:
                return False
        
        # If the position has been visited before, continue in the current direction
        if (r, c) in visited:
            dr, dc = current_direction
        else:
            # Mark the cell as visited and change direction based on the cell's character
            visited.add((r, c))
            dr, dc = directions[matrix[r][c]]
            current_direction = (dr, dc)
        
        # Move to the next position
        r, c = r + dr, c + dc


# Test Script
def test():
    # Test case 1
    matrix = [
        ['R', 'D', 'L'],
        ['L', 'U', 'R'],
        ['U', 'L', 'U']
    ]
    home = (0, 2)
    start = (1, 2)
    try:
        result = solution(matrix, start, home)
    except Exception as e:
        error_message = (
            f"An exception occurred while running the test case:\n"
            f"`matrix`:\n{'\n'.join([str(row) for row in matrix])}\n"
            f"`start`: {start}\n"
            f"`home`: {home}\n\n"
            f"Exception: '{str(e)}'"
        )
        assert False, error_message

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

    # Test case 2
    matrix = [
        ['R', 'D', 'L'],
        ['L', 'U', 'R'],
        ['U', 'L', 'U']
    ]
    home = (2, 0)
    start = (2, 2)
    try:
        result = solution(matrix, start, home)
    except Exception as e:
        error_message = (
            f"An exception occurred while running the test case:\n"
            f"`matrix`:\n{'\n'.join([str(row) for row in matrix])}\n"
            f"`start`: {start}\n"
            f"`home`: {home}\n\n"
            f"Exception: '{str(e)}'"
        )
        assert False, error_message

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

    # Test case 3
    matrix = [
        ['D', 'R', 'L', 'D'],
        ['U', 'L', 'U', 'L'],
        ['D', 'U', 'U', 'R'],
        ['R', 'D', 'D', 'L']
    ]
    home = (0, 3)
    start = (1, 3)
    try:
        result = solution(matrix, start, home)
    except Exception as e:
        error_message = (
            f"An exception occurred while running the test case:\n"
            f"`matrix`:\n{'\n'.join([str(row) for row in matrix])}\n"
            f"`start`: {start}\n"
            f"`home`: {home}\n\n"
            f"Exception: '{str(e)}'"
        )
        assert False, error_message

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

    # Test case 4
    matrix = [
        ['D', 'R', 'L', 'D'],
        ['U', 'L', 'U', 'L'],
        ['D', 'U', 'U', 'R'],
        ['R', 'D', 'D', 'L']
    ]
    home = (5, 1)
    start = (2, 2)
    try:
        result = solution(matrix, start, home)
    except Exception as e:
        error_message = (
            f"An exception occurred while running the test case:\n"
            f"`matrix`:\n{'\n'.join([str(row) for row in matrix])}\n"
            f"`start`: {start}\n"
            f"`home`: {home}\n\n"
            f"Exception: '{str(e)}'"
        )
        assert False, error_message

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

    # Test case 5
    matrix = [
        ['D', 'R', 'D', 'D'],
        ['L', 'U', 'R', 'U']
    ]
    home = (2, 0)
    start = (1, 1)
    try:
        result = solution(matrix, start, home)
    except Exception as e:
        error_message = (
            f"An exception occurred while running the test case:\n"
            f"`matrix`:\n{'\n'.join([str(row) for row in matrix])}\n"
            f"`start`: {start}\n"
            f"`home`: {home}\n\n"
            f"Exception: '{str(e)}'"
        )
        assert False, error_message

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

    # Test case 6
    matrix = [
        ['D', 'R', 'D', 'D'],
        ['L', 'U', 'R', 'U']
    ]
    home = (3, 3)
    start = (1, 1)
    try:
        result = solution(matrix, start, home)
    except Exception as e:
        error_message = (
            f"An exception occurred while running the test case:\n"
            f"`matrix`:\n{'\n'.join([str(row) for row in matrix])}\n"
            f"`start`: {start}\n"
            f"`home`: {home}\n\n"
            f"Exception: '{str(e)}'"
        )
        assert False, error_message

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

    # Test case 7
    matrix = [
        ['D', 'R', 'D', 'U'],
        ['U', 'U', 'R', 'L'],
        ['L', 'D', 'R', 'U']
    ]
    home = (2, 0)
    start = (1, 3)
    try:
        result = solution(matrix, start, home)
    except Exception as e:
        error_message = (
            f"An exception occurred while running the test case:\n"
            f"`matrix`:\n{'\n'.join([str(row) for row in matrix])}\n"
            f"`start`: {start}\n"
            f"`home`: {home}\n\n"
            f"Exception: '{str(e)}'"
        )
        assert False, error_message

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

test()