# Problem Description
This is a matrix transformation problem where we need to implement a gravity-like shifting mechanism for binary values (1s) in a matrix. Given a matrix of 0s and 1s and a sequence of directional commands (U, R, D, L), we need to shift all 1s in the specified direction until they can't move further, either hitting the boundary or another 1, while maintaining their relative order within each row or column.

# Visual Facts
1. The input is a 3×3 binary matrix
2. The image shows four different transformations:
   - Move "U": Shifts 1s upward
   - Move "D": Shifts 1s downward
   - Move "L": Shifts 1s leftward
   - Move "R": Shifts 1s rightward
3. Each transformation shows:
   - Initial state (matrix representation)
   - Intermediate state (blue squares visualization)
   - Final state (matrix representation)
4. Blue squares represent 1s in the visualization
5. Empty squares represent 0s

# Visual Patterns
1. Movement Rules:
   - All 1s move simultaneously in the specified direction
   - 1s stack against the target edge or against other 1s
     - for example, [0, 1, 1] after applying "L" is [1, 1, 0]
   - The relative order of 1s within each line of movement is preserved
   - No merging or combining of 1s occurs

2. Conservation Properties:
   - The total number of 1s remains constant throughout transformations
   - No new 1s are created or destroyed

3. Stacking Behavior:
   - For vertical movements (U/D):
   * Movement occurs within each column independently
   * 1s stack from the target edge (top for U, bottom for D)
   
   - For horizontal movements (L/R):
   * Movement occurs within each row independently
   * 1s stack from the target edge (left for L, right for R)

4. Empty Space Handling:
   - Spaces vacated by moved 1s are filled with 0s
   - 0s are displaced to the opposite side of the movement direction


# Solution
from typing import List

def solution(matrix: List[List[int]], operations: List[str]) -> List[List[int]]:
    """
    Transforms a matrix by applying a sequence of directional operations.

    Args:
        matrix: A 2D integer matrix (size M*N) represented as a list of lists.
        operations: A list of operations encoded as strings ("L", "R", "U", "D").

    Returns:
        The transformed matrix after applying all operations in sequence.
    """
    rows = len(matrix)
    cols = len(matrix[0])
    
    def move_up(mat):
        """Move all 1s up."""
        for col in range(cols):
            stack = [mat[row][col] for row in range(rows) if mat[row][col] == 1]
            for row in range(rows):
                mat[row][col] = 1 if row < len(stack) else 0
        return mat

    def move_down(mat):
        """Move all 1s down."""
        for col in range(cols):
            stack = [mat[row][col] for row in range(rows) if mat[row][col] == 1]
            for row in range(rows):
                mat[row][col] = 1 if row >= rows - len(stack) else 0
        return mat

    def move_left(mat):
        """Move all 1s left."""
        for row in range(rows):
            stack = [mat[row][col] for col in range(cols) if mat[row][col] == 1]
            for col in range(cols):
                mat[row][col] = 1 if col < len(stack) else 0
        return mat

    def move_right(mat):
        """Move all 1s right."""
        for row in range(rows):
            stack = [mat[row][col] for col in range(cols) if mat[row][col] == 1]
            for col in range(cols):
                mat[row][col] = 1 if col >= cols - len(stack) else 0
        return mat

    # Apply each operation in sequence
    for op in operations:
        if op == "U":
            matrix = move_up(matrix)
        elif op == "D":
            matrix = move_down(matrix)
        elif op == "L":
            matrix = move_left(matrix)
        elif op == "R":
            matrix = move_right(matrix)
    
    return matrix


# Test Script
def test():
    test_cases = [
        {
            "matrix": [
                [1, 0, 0],
                [1, 0, 1],
                [1, 1, 1]
            ],
            "operations": ["U"],
            "expected": [
                [1, 1, 1],
                [1, 0, 1],
                [1, 0, 0]
            ]
        },
        {
            "matrix": [
                [1, 0, 0],
                [0, 1, 0],
                [1, 1, 1]
            ],
            "operations": ["R"],
            "expected":  [[0, 0, 1], [0, 0, 1], [1, 1, 1]]
        },
        {
            "matrix": [
                [1, 0, 0],
                [0, 1, 0],
                [1, 1, 1]
            ],
            "operations": ["D", "L"],
            "expected": [[0, 0, 0], [1, 1, 0], [1, 1, 1]]
        },
        {
            "matrix": [
                [1, 0, 0],
                [1, 0, 1],
                [1, 1, 1]
            ],
            "operations": ["U","L","D","R"],
            "expected": [[0, 0, 1], [0, 1, 1], [1, 1, 1]]
        },
        {
            "matrix": [
                [1, 1, 1],
                [0, 1, 1],
                [0, 0, 1]
            ],
            "operations": ["D","L"],
            "expected": [[1, 0, 0], [1, 1, 0], [1, 1, 1]]
        },
        {
            "matrix": [
                [1, 1, 1],
                [0, 1, 1],
                [0, 0, 1]
            ],
            "operations": ["D","L","R","U"],
            "expected": [[1, 1, 1], [0, 1, 1], [0, 0, 1]]
        },
        {
            "matrix": [
                [1, 1, 1],
                [0, 0, 1],
                [1, 0, 1]
            ],
            "operations": ["D","R"],
            "expected": [[0, 0, 1], [0, 1, 1], [1, 1, 1]]
        },
        {
            "matrix": [
                [1, 1, 1, 1, 0],
                [0, 0, 1, 0, 0],
                [1, 0, 1, 1, 1],
                [1, 0, 0, 1, 1]
            ],
            "operations": ["D","R","U"],
            "expected": [[1, 1, 1, 1, 1], [0, 1, 1, 1, 1], [0, 0, 1, 1, 1], [0, 0, 0, 0, 0]]
        },
                {
            "matrix": [
                [1, 1, 1, 1, 0],
                [0, 0, 1, 0, 0],
                [1, 0, 1, 1, 1],
                [1, 0, 0, 1, 1]
            ],
            "operations": ["D","R","U","L"],
            "expected": [[1, 1, 1, 1, 1], [1, 1, 1, 1, 0], [1, 1, 1, 0, 0], [0, 0, 0, 0, 0]]
        },
                {
            "matrix": [
                [1, 1, 1, 1, 0],
                [0, 0, 1, 0, 0],
                [1, 0, 1, 1, 1],
                [1, 0, 0, 1, 1]
            ],
            "operations": ["D","D","R","U"],
            "expected": [[1, 1, 1, 1, 1], [0, 1, 1, 1, 1], [0, 0, 1, 1, 1], [0, 0, 0, 0, 0]]
        },
    ]

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

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

test()