# Problem Description
This problem involves determining if a ball starting from a given position with an initial direction can reach any of the holes on a 10x10 grid. The ball follows the law of reflection when it hits the boundaries of the grid. The task is to simulate the ball's movement and check if it eventually falls into one of the holes.

# Visual Facts
1. The coordinate system is a 10x10 grid (from 0 to 10 on both axes).
2. The grid has clear boundaries at x=0, x=10, y=0, and y=10.
3. The start point (green circle) is located at (8, 8).
4. There are two holes (black circles) located at (2, 2) and (2, 8).
5. The path is shown with blue dotted lines.
6. Blue arrows indicate the direction of movement.
7. The path shows multiple bounces off the boundaries.
8. The path eventually reaches one of the holes.
9. The path follows straight lines between bounces.

# Visual Patterns
1. **Bouncing Pattern**:
   - When the ball hits a boundary, it reflects with equal angles.
   - The angle of reflection equals the angle of incidence.
   - The ball maintains a constant direction between bounces.

2. **Movement Constraints**:
   - Movement is continuous along straight lines.（x += dx，y += dy）
   - Direction changes only occur at boundaries.
   - The ball's direction vector components (dx, dy) can be -1, 0, or 1.
   - The path never passes through the same point with the same direction twice (suggests a termination condition)

3. **Geometric Properties**:
   - The trajectory forms a series of connected line segments
   - Each bounce preserves the angle but reverses one component of the direction vector
   - For example, if the original direction (dx, dy) is (1, 1), and the x boundary is encountered (x == 0 or x == 10), then dx = -dx, and the new direction becomes (-1, 1).
   - For example, if the original direction (dx, dy) is (1, 1), and the y boundary is encountered (y == 0 or y == 10), then dy = -dy, and the new direction becomes (1, -1).
   - The path remains within the 10x10 grid boundaries at all times

4. **Solution Pattern**:
   - To reach a hole, the ball must follow a valid sequence of bounces.
   - A valid solution exists if there's a path connecting the start to any hole following reflection rules.
   - The ball's movement can be simulated step-by-step to check if it reaches a hole.

5. **Step to solve**:
   1. First, determine the positions of the two holes: (2, 2) and (2, 8).
   2. Then, enter a loop to simulate the ball's movement in the grid.
   3. In each iteration, update the ball's position: x += dx, y += dy.
   4. If the current ball's position (x, y) is either (2, 2) or (2, 8), exit the loop, as the ball has entered a hole.
   5. If the ball encounters a boundary where x == 0 or x == 10, then set dx = -dx.
   6. If the ball encounters a boundary where y == 0 or y == 10, then set dy = -dy.
   7. Exit the loop when the ball returns to the starting point and the direction is the same as the initial direction.

# Solution
def solution(start: tuple[int, int], direction: tuple[int, int]) -> bool:
    """
    Determines whether the ball can go into the hole

    Parameters:
    - start: Tuple[int, int], represents the initial position of the ball (x, y).
    - direction: Tuple[int, int], represents the initial direction of the ball (dx, dy). dx and dy are integers that can be either -1, 0, or 1.

    Returns:
    - bool: True if the ball can go into the hole, False otherwise.
    """
    x, y = start
    tx1, ty1 = (2, 2)
    tx2, ty2 = (2, 8)
    dx, dy = direction
    while True:
        x += dx
        y += dy
        if (x, y) == (tx1, ty1) or (x, y) == (tx2, ty2):
            return True
        if x == 0 or x == 10:
            dx = -dx
        if y == 0 or y == 10:
            dy = -dy
        if (x, y) == start and (dx, dy) == direction:
            return False


# Test Script
def test():
    test_cases = [
        [(8, 7), (1, -1), False],
        [(8, 7), (-1, -1), False],
        [(8, 8), (1, -1), True],
        
        [(0, 0), (1, 0), False],
        [(0, 0), (1, 1), True],
        [(0, 0), (0, 1), False],
        
        [(2, 1), (-1, -1), False],
        [(2, 1), (0, 1), True],
        
        [(10, 1), (-1, 1), False],
        [(7, 1), (1, 1), True],
    ]
    
    for test_case in test_cases:
        start, direction, expected_output = test_case
        
        try:
            output = solution(start, direction)
        except Exception as e:
            error_message = (
                f"An exception occurred while running the test case:\n"
                f"`start`: {start}\n"
                f"`direction`: {direction}\n\n"
                f"Exception: '{str(e)}'"
            )
            assert False, error_message

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

test()