# Problem Description
This problem involves rearranging a vertical stack of blocks labeled with letters based on a series of operations. Each operation specifies an index in the stack, and the transformation involves lifting the block at that index and all blocks above it, then moving all blocks below the lifted block to the top of the stack. The goal is to determine the final arrangement of blocks after all operations are applied.

# Visual Facts
1. Blocks are arranged vertically and labeled with letters (A, B, C, D).
2. Each position in the stack has an index starting from 0 at the top.
3. Operations are represented as a list of integers.
4. Example 1 shows Operations=[0].
5. Example 2 shows Operations=[0].
6. Example 3 shows Operations=[2,0,2].
7. Blue highlighting appears around certain blocks during transformations.
8. Dotted arrows indicate the movement of blocks.
9. Each transformation step maintains the total number of blocks.
10. Blocks below the lifted block move to the top of the stack.

# Visual Patterns
1. **Block Movement Pattern**:
   - When an operation occurs, the block at the specified index and all blocks above it are lifted (highlighted with blue borders).
   - The blocks below the lifted block are moved to the top of the stack.
   - The lifted blocks are then placed below the moved blocks.

2. **Operation Index Pattern**:
   - The operation number indicates which block position (0-based index) initiates the transformation.
   - Example 1: operation [0] moves block B and all blocks above it to the top.
   - Example 2: operation [0] moves block C and all blocks above it to the top.
   - Example 3: sequence [2,0,2] shows multiple transformations, each following the same pattern.

3. **Transformation Rules**:
   - Suppose the operation is at index i. The blocks from index 0 to i are lifted.
   - The blocks from index i+1 to the end of the stack are moved to the top.
   - The lifted blocks are then placed below the moved blocks.
   - The original relative order of the blocks is preserved within the moved and lifted groups.
   - The total height of the stack remains constant.


# Solution
from typing import List

def solution(initial_blocks: List[str], operations: List[int]) -> List[str]:
    """
    Calculates the final arrangement of blocks after applying a series of transformation operations.   

    Args:
        initial_blocks: List of strings representing the initial order of blocks from top to bottom
        operations: List of integers, indicating 0-based index positions involved in a transformation

    Returns:
        List of strings representing the final arrangement of blocks after all operations
    """
    current_stack = initial_blocks[:]

    for op in operations:
        # Determine the range of blue blocks based on the last block's index
        k = op + 1  # Include the block at index `op`
        
        if k > len(current_stack):
            raise ValueError(f"Operation {op} cannot be performed on the current stack: {current_stack}")

        # Split the current stack into blue blocks and remaining stack
        blue_blocks = current_stack[:k]
        remaining_stack = current_stack[k:]

        # Move the first block of the remaining stack to the top (if any)
        if remaining_stack:
            block_to_move = remaining_stack.pop(0)
            current_stack = [block_to_move] + remaining_stack + blue_blocks 
        else:
            current_stack = blue_blocks

    return current_stack


# Test Script
def test():
    test_cases = [
        (
            ["A", "B", "C"],
            [],
            ["A", "B", "C"]
        ),
        
        (
            ["B1", "C"],
            [0],
            ["C", "B1"]
        ),
        
        (
            ["B1", "B2", "C", "D"],
            [1],
            ["C", "D","B1", "B2"]
        ),
        
        (
            ["B1", "B2", "C", "D", "E"],
            [1, 1],
            ["E","B1", "B2","C", "D" ]
        ),
        
        (
            ["B1", "B2"],
            [1],
            ["B1", "B2"]
        ),
        
        (
            ["B1", "B2", "C", "D", "E"],
            [1, 0],
            ["D", "E", "B1", "B2","C"]
        ),
        
        (
            ["B1", "B2", "C", "D", "E", "F"],
            [1, 1, 1],
            ["B1", "B2","C", "D","E", "F"]
        ),
        
        (
            ["C", "A", "B", "D"],
            [1, 1],
            ["C", "A", "B", "D"]
        ),
        (
            ["C","B","D","A"],
            [0,2,1],
            ["D","A","C","B"]
        )
    ]

    for i, (initial_blocks, operations, expected_output) in enumerate(test_cases):
        try:
            output = solution(initial_blocks, operations)
        except Exception as e:
            error_message = (
                f"An exception occurred while running the test case:\n"
                f"`initial_blocks`: {initial_blocks}\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_blocks`: {initial_blocks}\n"
                f"`operations`: {operations}\n\n"
                f"Actual Output: {output}\n"
                f"Expected Output: {expected_output}"
            )
            assert False, error_message

test()