# Problem Description
This is a cube restoration verification problem where:
- We have a 3×3 matrix (cube face) with initial values
- We can perform operations on rows and columns
- Each operation involves shifting elements cyclically in a specified direction
- The operation symbol and the actual operation direction are opposite.
- We need to determine if the cube is ordered
- The goal is to track the transformations and verify the final state is identical to [[1,2,3],[4,5,6],[7,8,9]]

# Visual Facts
1. Matrix Structure:
   - 3×3 grid layout
   - Columns labeled as A, B, C (top)
   - Rows labeled as D, E, F (left)
   - Each cell contains a single integer

2. Operations Types:
   - Row operations: L , R
   - Column operations: U , D

3. Movement Rules:
    **Columns**  
   - **A, B, C** correspond to the first, second, and third columns respectively.  
   - **D** actually refers to **Up** which means cyclically shifting a column’s elements one step upward (the top element moves to the bottom, and all other elements shift up by one).  
   - **U** actually refers to **Down** which means cyclically shifting a column’s elements one step downward (the bottom element moves to the top, and all other elements shift down by one).

   **Rows**  
   - **D, E, F** correspond to the first, second, and third rows respectively.  
   - **L**  actually refers to **Right** which means cyclically shifting a row’s elements one step to the right (the rightmost element moves to the left end, and others shift right by one).  
   - **R**  actually refers to **Left** which means cyclically shifting a row’s elements one step to the left (the leftmost element moves to the right end, and others shift left by one).
   
   - For a row, op L: 
      [1,2,3] → [3,1,2]
   - For a row, op R: 
      [1,2,3] → [2,3,1]
   - For a column, op U: 
      [
         [1],
         [2],
         [3]
      ] 
      → 
      [
         [3],
         [1],
         [2]
      ]
   - For a column, op D: 
   [
      [1],
      [2],
      [3]
   ] 
   → 
   [
      [2],
      [3],
      [1]
   ]


# Visual Patterns

1. Operation Properties:
   - Row operations affect exactly 3 numbers horizontally
   - Column operations affect exactly 3 numbers vertically
   - Each operation moves elements by one position in the specified direction
   - The goal is checking the final state is identical to [[1,2,3],[4,5,6],[7,8,9]] 

# Solution
from typing import List, Tuple

def solution(initial_matrix: List[List[int]], operations: List[Tuple[str, str]]) -> bool:
    """
    Determines whether a cube is ordered after performing a sequence of operations.

    Args:
        initial_matrix: A 3x3 matrix represented as a list of lists, where each inner list contains three integers representing the initial state of the cube.
        operations: A list of operation tuples, where each tuple contains:
                   - First element: A character in {'A', 'B', 'C', 'D', 'E', 'F'}
                   - Second element: A direction character in {'R', 'L', 'U', 'D'}

    Returns:
        bool: True if the cube is ordered after all operations, False otherwise.
    """
    target_matrix = [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]
    ]

    # Helper functions for row and column operations
    def move_row(matrix, row_idx, direction):
        """Move a row left (L) or right (R)."""
        if direction == 'R':
            matrix[row_idx] = matrix[row_idx][1:] + [matrix[row_idx][0]]
        elif direction == 'L':
            matrix[row_idx] = [matrix[row_idx][-1]] + matrix[row_idx][:-1]

    def move_col(matrix, col_idx, direction):
        """Move a column up (U) or down (D)."""
        col = [matrix[i][col_idx] for i in range(3)]  # Extract the column
        if direction == 'D':
            col = col[1:] + [col[0]]  # Shift column up
        elif direction == 'U':
            col = [col[-1]] + col[:-1]  # Shift column down
        for i in range(3):  # Write back the column
            matrix[i][col_idx] = col[i]

    # Apply operations
    for op in operations:
        part, direction = op
        if part in 'DEF':  # Row operation
            row_idx = ord(part) - ord('D')  # Map D->0, E->1, F->2
            move_row(initial_matrix, row_idx, direction)
        elif part in 'ABC':  # Column operation
            col_idx = ord(part) - ord('A')  # Map A->0, B->1, C->2
            move_col(initial_matrix, col_idx, direction)

    # Check if the matrix matches the target state
    return initial_matrix == target_matrix


# Test Script
def test():
    test_cases = [
        # Test Case 1: Simple row shift to restore
        {
            "input_matrix": [
                [2, 3, 1],
                [4, 5, 6],
                [7, 8, 9]
            ],
            "operations": [("D", "L"), ("D", "L"), ("D", "R")],
            "expected": True
        },
        # Test Case 2: Already in restored state
        {
            "input_matrix": [
                [1, 2, 3],
                [4, 5, 6],
                [7, 8, 9]
            ],
            "operations": [],
            "expected": True
        },
        # Test Case 3: Impossible to restore
        {
            "input_matrix": [
                [1, 2, 3],
                [5, 4, 6],
                [7, 9, 8]
            ],
            "operations": [("E", "R"), ("F", "L")],
            "expected": False
        },
        # Test Case 4: Multiple shifts to restore
        {
            "input_matrix": [
                [3, 1, 2],
                [6, 4, 5],
                [9, 7, 8]
            ],
            "operations": [("D", "L"), ("D", "L"), ("E", "R"), ("F", "R")],
            "expected": True
        },
        # Test Case 5: Full reversal and restore
        {
            "input_matrix": [
                [4, 5, 6],
                [7, 8, 9],
                [1, 2, 3]
            ],
            "operations": [("A", "D"), ("A", "D"), ("B", "D"), ("B", "D"), ("C", "D"), ("C", "D")],
            "expected": True
        },
        # Test Case 6: Single column shift
        {
            "input_matrix": [
                [4, 5, 2],
                [7, 8, 6],
                [3, 1, 9]
            ],
            "operations": [("A", "U"), ("B", "U"), ("D", "R")],
            "expected": True
        },
        # Test Case 7: No operations, wrong state
        {
            "input_matrix": [
                [2, 1, 3],
                [4, 5, 6],
                [7, 8, 9]
            ],
            "operations": [("A", "U"), ("B", "U"), ("D", "R"), ("D", "R"),("F", "D")],
            "expected": False
        },
        # Test Case 8: Diagonal swap, cannot restore
        {
            "input_matrix": [
                [1, 2, 3],
                [5, 4, 6],
                [7, 9, 8]
            ],
            "operations": [("D", "R"), ("E", "R")],
            "expected": False
        }
    ]

    for i, test_case in enumerate(test_cases, start=1):
        initial_matrix = [row[:] for row in test_case["input_matrix"]]
        operations = test_case["operations"]
        expected_output = test_case["expected"]

        try:
            output = solution(initial_matrix, operations)
        except Exception as e:
            error_message = (
                f"An exception occurred while running the test case:\n"
                f"`initial_matrix`:\n"
                f"{initial_matrix[0]}\n"
                f"{initial_matrix[1]}\n" 
                f"{initial_matrix[2]}\n\n"
                f"`operations`: {operations}\n\n"
                f"Exception: '{str(e)}'"
            )
            assert False, error_message

        if output != expected_output:
            error_message = (
                f"The following Test Case failed:\n"
                f"`initial_matrix`:\n"
                f"{initial_matrix[0]}\n"
                f"{initial_matrix[1]}\n"
                f"{initial_matrix[2]}\n\n"
                f"`operations`: {operations}\n\n"
                f"Actual Output: {output}\n"
                f"Expected Output: {expected_output}"
            )
            assert False, error_message

test()