# Problem Description
This is a cup-swapping puzzle where:
- There are 4 cups numbered from 1 to 4
- A red ball is placed under one of the cups initially
- Three possible swap operations (A, B, C) can be performed in sequence
- We need to track and return the final position of the ball after all swaps
- Each operation represents a specific pair of cups exchanging positions
- Positions are 1-indexed (1 to 4)

# Visual Facts
1. There are exactly 3 different swap operations (A, B, C)
2. Each operation swaps exactly two adjacent cups
3. Cups are indexed 1, 2, 3, and 4 from left to right
4. A red ball appears under different cups to demonstrate movement
5. Curved arrows show the direction of swaps
6. The specific swaps are:
   - A: swaps cups 1↔2
   - B: swaps cups 3↔4
   - C: swaps cups 2↔3

# Visual Patterns
1. Position Pattern:
   - The ball always moves with its cup during a swap
   - Each swap only affects two adjacent cups
   - The unaffected cups remain stationary during each swap
   - All swaps are between adjacent positions only

2. Operation Properties:
   - Each swap operation is reversible (performing same swap twice restores original positions)
   - Swaps can be performed in sequence
   - The ball's final position depends on:
     * Its initial position (1-4)
     * The sequence of swaps performed (A, B, or C)

3. Mathematical Patterns:
   - A swap operation changes the ball's position only if it's in one of the cups being swapped
   - If the ball is in an unaffected cup, its position remains unchanged


# Solution
from typing import List

def solution(swaps: List[str], initial_position: int) -> int:
    """
    Determine the final position of the ball after a series of swaps.

    Parameters:
        swaps (List[str]): A list of operation ids ('A', 'B', 'C') representing the sequence of cup swap operations.
        initial_position (int): The index of the cup where the ball is initially placed. (1-indexed)

    Returns:
        int: The index of the cup where the ball is finally located. (1-indexed)
    """
    swap_operations = {
        'A': (1, 2),
        'B': (3, 4),
        'C': (2, 3),
    }
    
    position = initial_position
    
    for swap in swaps:
        if swap in swap_operations:
            cup1, cup2 = swap_operations[swap]
            if position == cup1:
                position = cup2
            elif position == cup2:
                position = cup1
    
    return position


# Test Script
def test():
    test_cases = [
        (['A'], 1, 2),
        (['A'], 3, 3),
        (['B'], 3, 4),
        (['A', 'B', 'C'], 2, 1),
        (['C', 'A', 'A', 'C', 'B'], 4, 3),
        (['B', 'C', 'A', 'B', 'C', 'B', 'A'], 3, 1),
        (['A', 'C', 'B', 'C'], 1, 4),
        (['A', 'B', 'B', 'C', 'C', 'B', 'A', 'C', 'B'], 2, 4),
        (['B', 'A', 'A', 'C', 'B', 'C', 'A'], 4, 3),
        (['A', 'B', 'C', 'B', 'A', 'C', 'B'], 1, 3),
        (['B', 'A', 'B', 'C', 'A', 'C', 'B', 'A', 'C', 'A', 'B', 'A', 'C'], 4, 3),
    ]

    for i, (swaps, initial_position, expected_output) in enumerate(test_cases):
        original_swaps = swaps[:]
        try:
            # Create a copy of swaps to preserve original input
            output = solution(swaps, initial_position)
        except Exception as e:
            error_message = (
                f"An exception occurred while running the test case:\n"
                f"`swaps`: {original_swaps}\n"
                f"`initial_position`: {initial_position}\n\n"
                f"Exception: '{str(e)}'"
            )
            assert False, error_message

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

test()