# Problem Description
This problem involves performing a pooling operation on a given 2D matrix. The pooling operation reduces the size of the matrix by processing 2x2 regions into single values in the output matrix. The goal is to implement this transformation according to the pattern shown in the examples.

# Visual Facts
1. Example Case 1:
   - Input: 2x2 matrix
   - Output: 1x1 matrix
   - The value in the output matrix is the value with the maximum absolute value from the input matrix.

2. Example Case 2:
   - Input: 4x4 matrix
   - Output: 2x2 matrix
   - Each 2x2 section in the input matrix maps to one value in the output matrix.
   - The values in the output matrix are the value with the maximum absolute values from the corresponding 2x2 sections in the input matrix.

3. Example Case 3:
   - Input: 6x6 matrix
   - Output: 3x3 matrix
   - Each 2x2 section in the input matrix maps to one value in the output matrix.
   - The values in the output matrix are the value with the maximum absolute values from the corresponding 2x2 sections in the input matrix.

# Visual Patterns
1. Size Reduction Pattern:
   - The output matrix size is always half of the input matrix in each dimension.
   - The input dimensions must be even numbers.
   - For an input matrix of size n×n, the output matrix will be of size (n/2)×(n/2).

2. Value Selection Pattern:
   - Each 2x2 block in the input matrix maps to a single value in the output matrix.
   - The selected value is the maximum absolute value from each 2x2 block.
   - For any 2x2 block:
     ```
     [a b]
     [c d]
     ```
     The output absolute value is max(|a|, |b|, |c|, |d|), and the sign of the output should remain the same as the original value's sign. For example, if |b| has the largest absolute value and b is negative, the output will be -|b|.

3. Scanning Pattern:
   - The matrix is scanned from left to right, top to bottom.
   - Each 2x2 non-overlapping block is processed independently.
   - No blocks overlap or share elements.

4. General Rule:
   - For an input matrix of size n×n:
     - |Output[i][j]| = max(|Input[2i][2j]|, |Input[2i][2j+1]|, |Input[2i+1][2j]|, |Input[2i+1][2j+1]|)
     - The sign of the output is determined by the sign of the value with the largest absolute value in the 2x2 block.
     where i and j are indices in the output matrix.

# Solution
def solution(matrix: list[list[int]]) -> list[list[int]]:
    """
    Refer to the example cases illustrated in the figure, identify and implement the pooling operation on the matrix.

    Input:
    - matrix: A 2d list representing the initial matrix. For example, [[1,3,4,2], [2,1,1,3], [1,2,2,4], [3,2,1,0]]

    Output:
    - A 2d list representing the resulting matrix after the pooling operation.
    """
    rows = len(matrix)
    cols = len(matrix[0])
    pooled_matrix = []
    for i in range(0, rows, 2):
        pooled_row = []
        for j in range(0, cols, 2):
            block = [
                matrix[i][j], 
                matrix[i][j + 1] if j + 1 < cols else 0, 
                matrix[i + 1][j] if i + 1 < rows else 0, 
                matrix[i + 1][j + 1] if i + 1 < rows and j + 1 < cols else 0
            ]
            max_value = max(abs(num) for num in  block)
            pooled_row.append(max_value if max_value in block else -max_value)
        pooled_matrix.append(pooled_row)
    return pooled_matrix


# Test Script
def test():
    test_cases = [
        {
            "input": [
                [1, -2],
                [3, 4]
            ],
            "expected": [
                [4]
            ] 
        },
        {
            "input": [
                [1, 3, 4, 2],
                [2, 1, 1, 3],
                [1, 2, 2, 4],
                [3, 2, 1, 0]
            ],
            "expected": [
                [3, 4], 
                 [3, 4]
            ]
        }, {
            "input": [
                [1, 2, 3, 4],
                [5, -6, 7, -8],
                [-9, -10, -11, 12],
                [13, 14, 15, -16]
            ],
            "expected": [
                [-6, -8], 
                [14, -16]
            ]
        }, {
            "input": [
                [1, 1],
                [1, 10]
            ],
            "expected": [
                [10]
            ]
        }, {
            "input": [
                [1, -2, 3, 4, 5, -6],
                [12, 11, -10, 9, 8, 7],
                [13, 14, 15, 16, -17, 18],
                [-19, 20, 21, 22, 23, 24],
                [-30, -29, 28, 27, 26, 25],
                [31, 32, 33, -34, 35, -36]
            ],
            "expected": [
                [12, -10, 8], 
                [20, 22, 24], 
                [32, -34, -36]
            ]
        }
    ]
    for i, test_case in enumerate(test_cases):
        matrix = test_case["input"]
        expected_output = test_case["expected"]

        try:
            output = solution(matrix)
        except Exception as e:
            error_message = (
                f"An exception occurred while running the test case:\n"
                f"`matrix`:\n"
            )
            # Print matrix row by row for better readability
            for row in matrix:
                error_message += f"{row}\n"
            error_message += f"\nException: '{str(e)}'"
            assert False, error_message

        if output != expected_output:
            error_message = (
                f"The following Test Case failed:\n"
                f"`matrix`:\n"
            )
            # Print matrix row by row for better readability
            for row in matrix:
                error_message += f"{row}\n"
            error_message += (
                f"\nActual Output:\n"
            )
            for row in output:
                error_message += f"{row}\n"
            error_message += (
                f"\nExpected Output:\n"
            )
            for row in expected_output:
                error_message += f"{row}\n"
            assert False, error_message

test()