# Problem Description
This is a cup-swapping puzzle where:
- There are 4 cups numbered 1 to 4 arranged in a row
- A red ball is placed under one of the cups initially
- A sequence of swap operations (A through D) is performed
- We need to track and return the final position of the ball
- Each operation represents a specific pair of cups being swapped
- The positions are 1-indexed (1 through 4)

# Visual Facts
1. There are 4 different swap operations labeled A through D
2. Each operation involves swapping exactly two adjacent or non-adjacent cups
3. The cups are numbered 1, 2, 3, and 4 from left to right
4. Curved arrows show which cups are swapped in each operation
5. The specific swaps shown are:
   - A: swaps cups 1↔2
   - B: swaps cups 1↔3
   - C: swaps cups 2↔3
   - D: swaps cups 3↔4
6. A red ball is used to demonstrate the movement

# Visual Patterns
1. Ball Movement Pattern:
   - The ball always moves with its cup during a swap
   - Only the two cups involved in the swap can change positions
   - Other cups remain stationary during each swap

2. Operation Properties:
   - Each swap operation is symmetric (reversible)
   - The same swap performed twice returns cups to their original positions
   - The ball's final position depends on:
     * Its initial position
     * The sequence of swaps performed


# 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', 'D') 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': (1, 3),
        'C': (2, 3),
        'D': (3, 4)
    }
    
    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, 1),
        (['A', 'B', 'D', 'C'], 2, 4),
        (['C', 'A', 'A', 'C', 'B'], 1, 3),
        (['B', 'C', 'A', 'B', 'D', 'C', 'B', 'A'], 3, 2),
        (['A', 'C', 'B', 'C'], 1, 1),
        (['A', 'B', 'B', 'C', 'C', 'B', 'A', 'C', 'B'], 2, 2),
        (['B', 'A', 'A', 'D', 'C', 'B', 'C', 'A'], 3, 1),
        (['A', 'B', 'C', 'B', 'D', 'A', 'C', 'B'], 1, 1),
        (['B', 'A', 'B', 'C', 'A', 'C', 'D', 'B', 'A', 'C', 'A', 'D', 'B', 'A', 'C'], 2, 2),
    ]

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

test()