# Problem Description
This is a matrix transformation problem where elements need to be rearranged according to specific movement rules. The input is a 2D matrix of integers, and the output is a transformed matrix of the same dimensions where elements have been moved according to a shift pattern.

# Visual Facts
1. The image shows 4 different example transformations:
   - 2×3 matrix transformation
   - 4×3 matrix transformation
   - 4×4 matrix transformation
   - 3×5 matrix transformation

2. Colors are used to track element movements:
   - Light blue cells
   - Orange cells

3. All input matrices have consistent color patterns:
   - First half of rows is always light blue
   - Another half of rows are orange

4. Output matrices maintain the same dimensions as their inputs

# Visual Patterns
1. Movement Rules:
   - Swap the Upper half of the matrix and lower half of the matrix. 
   - Note that the matrix will always have an even number of rows.(except one row)
   - If the matrix only contains one row, then no transformation will be done.

2. Pattern Consistency:
   - The transformation rules remain consistent regardless of matrix dimensions
   - The transformation preserves all original values, just rearranges them
   - The pattern works for both positive and negative integers


# Solution
def solution(matrix: list[list[int]]) -> list[list[int]]:
    """
    Manipulates a 2D matrix of integers according to the demonstrated transformation rules. Note that the matrix will always have an even number of rows.

    Parameters:
        matrix (list[list[int]]): A 2D matrix of integers.

    Returns:
        list[list[int]]: The transformed matrix of the same dimensions as the input.       
    """
    # Initialize the row and column sizes
    rows = len(matrix)
    cols = len(matrix[0])
    if rows == 1:
        return matrix
    # Initialize the new matrix
    new_matrix = [[0] * cols for _ in range(rows)]

    new_matrix[:rows//2] = matrix[rows//2:]
    new_matrix[rows//2:] = matrix[:rows//2]
    return new_matrix


# Test Script
def test():
    test_cases = [
        ([[6, 5, 8], [1, 8, 2]], [[1, 8, 2], [6, 5, 8]]),
        ([[8, 2, 6], [4, 0, 7], [2, 1, 6], [2,8,4]], [[2, 1, 6], [2, 8, 4], [8, 2, 6], [4, 0, 7]]),
        ([[8, 2, 6], [4, 0, 7], [2, 1, 6],[3,2,4]], [[2, 1, 6], [3, 2, 4], [8, 2, 6], [4, 0, 7]]),
        ([[8, 1, 5, 9, 1, 4]], [[8, 1, 5, 9, 1, 4]]),
        ([[0, 1, 0], [7, 6, 6], [7, 3, 3], [6, 6, 4], [3, 9, 7], [6, 1, 9]], [[6, 6, 4], [3, 9, 7], [6, 1, 9], [0, 1, 0], [7, 6, 6], [7, 3, 3]]),
        ([[6], [3]], [[3], [6]]),
        ([[4, 9], [2, 4]], [[2, 4], [4, 9]]),
        ([[6, 8, 8, 7], [5, 0, 4, 6], [9, 9, 9, 8], [2, 1, 7, 9], [4, 8, 1, 9], [9, 9, 0, 0]], [[2, 1, 7, 9], [4, 8, 1, 9], [9, 9, 0, 0], [6, 8, 8, 7], [5, 0, 4, 6], [9, 9, 9, 8]]),
        ([[8, 5, 2, 0, 8, 5], [8, 1, 4, 3, 5, 8], [6, 0, 8, 0, 6, 3], [5, 1, 0, 5, 9, 0]], [[6, 0, 8, 0, 6, 3], [5, 1, 0, 5, 9, 0], [8, 5, 2, 0, 8, 5], [8, 1, 4, 3, 5, 8]]),
        ([[6, 9, 1, 3], [5, 8, 9, 8], [5, 2, 7, 9], [8, 0, 9, 6]],  [[5, 2, 7, 9], [8, 0, 9, 6], [6, 9, 1, 3], [5, 8, 9, 8]])
    ]

    for matrix, expected_output in test_cases:
        try:
            output = solution(matrix)
        except Exception as e:
            error_message = (
                f"An exception occurred while running the test case:\n"
                f"`matrix`: {matrix}\n\n"
                f"Exception: '{str(e)}'"
            )
            assert False, error_message

        if output != expected_output:
            error_message = (
                f"The following Test Case failed:\n"
                f"`matrix`: {matrix}\n\n"
                f"Actual Output: {output}\n"
                f"Expected Output: {expected_output}"
            )
            assert False, error_message

test()