# Problem Description
This problem involves a grid-based transformation where we need to simulate the absorption of orange dots by purple lines emanating from a red triangle. The goal is to calculate the minimum number of iterations required to convert all orange dots into purple dots, following specific geometric rules of absorption.

# Visual Facts
1. **Grid Structure:**
   - The grid is a 4x4 coordinate system (0-3 on both axes).
   - Grid points are discrete integer coordinates.
   - The origin (0,0) is at the top-left corner.

2. **Components:**
   - One red triangle (fixed position).
   - Multiple orange dots (initial state).
   - Purple dots (transformed state).
   - Purple lines (transformation medium).

3. **Transformation Sequence:**
   - Initial state shows orange dots and one red triangle.
   - Iter1: Vertical line absorption.
   - Iter2: Diagonal line absorption.
   - Iter3: Horizontal line absorption.
   - Iter4: Final vertical absorption.
   - Process completes in exactly 4 iterations in the example.

# Visual Patterns
1. **Line Properties:**
   - Each purple line must pass through the red triangle.
   - Lines can be:
     * Vertical (constant x).
     * Horizontal (constant y).
     * Diagonal (linear with slope).
   - The line has only one direction, emitting from the red triangle.

2. **Absorption Rules:**
   - Any orange dot lying exactly on a purple line gets absorbed.
   - Multiple dots can be absorbed in a single iteration if they lie on the same line.
   - Each dot can only be absorbed once.
   - The line must pass through both the triangle and at least one orange dot.
   - The line is emitted unidirectionally from the red triangle. For example, if two purple points and the red triangle are on the same horizontal line, but one is to the left of the triangle and the other to the right, the triangle needs to emit two lines to absorb them.
   - Example：
      red_triangle=(3, 1), orange_dots=[(3, 0), (3, 2), (3, 3)]
      The orange dots and the red triangle share the same x-coordinate (3), but have different y-coordinates. It can be observed that (3, 0) and the other two orange dots are not on the same side.
      To convert the three orange dots, the red triangle needs to emit a purple line to (3, 0) first, and then emit another purple line to (3, 2) and (3, 3). Therefore, it takes a total of two iterations to convert them.


3. **Optimization Patterns:**
   - Lines are chosen to maximize the number of dots absorbed per iteration.
   - Dots that share geometric alignment (same x, y, or slope relative to triangle) should be absorbed together.
   - The order of absorption can affect the total number of iterations.
   - Priority seems to be given to lines that can absorb multiple dots simultaneously.

4. **Mathematical Constraints:**
   - For dots to be absorbed in the same iteration, they must satisfy one of:
     * Same x-coordinate as triangle (vertical line).
     * Same y-coordinate as triangle (horizontal line).
     * Share the same slope relative to triangle position (diagonal line).
     * Points must be collinear with the triangle.

5. **Iteration Strategy:**
   - Given the red triangle's position (x0, y0):
     - Traverse all the orange dots and classify each dot into a group according to the following rule.
     - Find the dots with xi=x0 and y>y0, these points belong to the same group.
     - Find the dots with xi=x0 and y<y0, these points belong to the same group.
     - Find the dots with yi=y0 and x>x0, these points belong to the same group.
     - Find the dots with yi=y0 and x<x0, these points belong to the same group.
     - Then compute all the slopes to the orange dots (yi-y0)/(xi-x0).
     - Slopes that are equal and have y > y0 belong to the same group, while slopes that are equal and have y<y0 belong to another group.
     - The total iteration is the number of groups.

# Solution
def solution(red_triangle: tuple, orange_dots: list) -> int:
    """
    Determine the number of iterations required to absorb all the orange dots.

    Parameters:
    red_triangle (tuple): The coordinates of the red triangle (x0, y0).
    orange_dots (list): A list of tuples, where each tuple represents the coordinates of an orange dot (xi, yi).

    Returns:
    int: The number of iterations.
    """
    x0, y0 = red_triangle
    slopes = set()

    for x, y in orange_dots:
        if x == x0:
            slopes.add('vertical+' if y > y0 else 'vertical-')
        elif y == y0:
            slopes.add('horizontal+' if x > x0 else 'horizontal-')
        else:
            slopes.add(f'+_{(y - y0) / (x - x0)}' if y > y0 else f'-_{(y - y0) / (x - x0)}')

    return len(slopes)

# Test Script
def test():
    test_cases = [
        ((2, 2), [(2, 4)], 1),
        ((3, 0), [(3, 1), (3, 2), (3, 3)], 1),
        ((0, 3), [(1, 3), (2, 3), (4, 3)], 1),
        ((3, 1), [(3, 0), (3, 2), (3, 3)], 2),
        ((2, 3), [(1, 3), (0, 3), (4, 3)], 2),
        ((2, 2), [(1, 1), (0, 0), (3, 3)], 2),
        ((2, 2), [(0, 2), (2, 4), (4, 4), (2, 0)], 4),
        ((2, 2), [], 0),
        ((1, 1), [(0, 0), (2, 2), (3, 3), (4, 4)], 2),
        ((2, 0), [(0, 0), (0, 1), (1, 3), (2, 1), (3, 2), (4, 0)], 6),
        ((2, 3), [(0, 3), (2, 1), (4, 3), (3, 4), (1, 5), (0, 5)], 6),
        ((5, 5), [(0, 0), (0, 5), (5, 0), (10, 5), (5, 10), (10, 10), (3, 5)], 6)
    ]

    for i, (red_triangle, orange_dots, expected_output) in enumerate(test_cases):
        try:
            output = solution(red_triangle, orange_dots)
        except Exception as e:
            error_message = (
                f"An exception occurred while running the test case:\n"
                f"`red_triangle`: {red_triangle}\n"
                f"`orange_dots`: {orange_dots}\n\n"
                f"Exception: '{str(e)}'"
            )
            assert False, error_message
            
        if output != expected_output:
            error_message = (
                f"The following Test Case failed:\n"
                f"`red_triangle`: {red_triangle}\n" 
                f"`orange_dots`: {orange_dots}\n\n"
                f"Actual Output: {output}\n"
                f"Expected Output: {expected_output}"
            )
            assert False, error_message

test()