# 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
- We need to determine if the cube is ordered
- The goal is to track the transformations and verify the final state matches the initial state

# 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: R (Right), L (Left)
   - Column operations: U (Up), D (Down)

3. Movement Rules:
   - Row R: [1,2,3] → [3,1,2]
   - Row L: [1,2,3] → [2,3,1]
   - Column D: [1,2,3] → [3,1,2]
   - Column U: [1,2,3] → [2,3,1]

4. Example Shows:
   - Initial state with numbers 1-9
   - Multiple operations sequence
   - Intermediate states after each operation
   - A "ordered cube" state highlighted in green border

# Visual Patterns
1. Cyclic Nature:
   - All operations are cyclic shifts
   - Each operation preserves all numbers in the row/column
   - No numbers are lost or modified, only positions change

2. 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

3. State Management:
   - The matrix state must be tracked after each operation
   - Operations can be reversed (R↔L, U↔D)
   - Multiple operations can lead back to the initial state

4. Restoration Conditions:
   - The cube is considered ordered when all numbers are in increasing order from 1 (row 1 col 1) to 9 (row 3 col 3)
   - The order of operations matters
   - Different operation sequences can lead to the same final state


# 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 == 'L':
            matrix[row_idx] = matrix[row_idx][1:] + [matrix[row_idx][0]]
        elif direction == 'R':
            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 == 'U':
            col = col[1:] + [col[0]]  # Shift column up
        elif direction == 'D':
            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", "R"), ("D", "R"), ("D", "L")],
            "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", "L"), ("F", "R")],
            "expected": False
        },
        # Test Case 4: Multiple shifts to restore
        {
            "input_matrix": [
                [3, 1, 2],
                [6, 4, 5],
                [9, 7, 8]
            ],
            "operations": [("D", "R"), ("D", "R"), ("E", "L"), ("F", "L")],
            "expected": True
        },
        # Test Case 5: Full reversal and restore
        {
            "input_matrix": [
                [4, 5, 6],
                [7, 8, 9],
                [1, 2, 3]
            ],
            "operations": [("A", "U"), ("A", "U"), ("B", "U"), ("B", "U"), ("C", "U"), ("C", "U")],
            "expected": True
        },
        # Test Case 6: Single column shift
        {
            "input_matrix": [
                [4, 5, 2],
                [7, 8, 6],
                [3, 1, 9]
            ],
            "operations": [("A", "D"), ("B", "D"), ("D", "L")],
            "expected": True
        },
        # Test Case 7: No operations, wrong state
        {
            "input_matrix": [
                [2, 1, 3],
                [4, 5, 6],
                [7, 8, 9]
            ],
            "operations": [("A", "D"), ("B", "D"), ("D", "L"), ("D", "L"),("F", "R")],
            "expected": False
        },
        # Test Case 8: Diagonal swap, cannot restore
        {
            "input_matrix": [
                [1, 2, 3],
                [5, 4, 6],
                [7, 9, 8]
            ],
            "operations": [("D", "L"), ("E", "L")],
            "expected": False
        }
    ]

    for i, test_case in enumerate(test_cases, start=1):
        initial_matrix = [row[:] for row in test_case["input_matrix"]]  # Copy to avoid modifying original
        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 test case {i}:\n"
                f"`initial_matrix`:\n"
                f"[\n"
                f"  {initial_matrix[0]}\n"
                f"  {initial_matrix[1]}\n"
                f"  {initial_matrix[2]}\n"
                f"]\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 {i} failed:\n"
                f"`initial_matrix`:\n"
                f"[\n"
                f"  {initial_matrix[0]}\n"
                f"  {initial_matrix[1]}\n"
                f"  {initial_matrix[2]}\n"
                f"]\n"
                f"`operations`: {operations}\n\n"
                f"Actual Output: {output}\n"
                f"Expected Output: {expected_output}"
            )
            assert False, error_message

test()