Path 1: 43 calls (0.83)

10 (4) 32 (4) 29 (3) 180 (3) 60 (3) 1 (3) 25 (3) 15 (3) 3 (2) 19 (2)

[0, 1, 0] (8) [0, 1, 0, 0] (7) [0, 1, 0, 1] (7) [0, 1] (6) [0, 1, 1] (6) [1, 1, 1, 1] (5) [0, 1, 1, 1] (3) [0, 0, 0, 1] (1)

[5, 5, 5, 5] (6) [5, 5, 5] (5) [29, 29] (3) [60, 60, 60, 60] (3) [60, 0, 60, 0] (3) [12, 12, 12] (3) [7, 7, 7, 7] (3) [19, 19] (2) [1, 1, 1, 1] (2) [1...

[22, 17, 5] (4) [17, 17, 5, 10] (4) [60, 60, 60, 60] (3) [60, 0, 60, 0] (3) [17, 10, 5, 10] (3) [17, 5, 5, 5] (3) [14, 37, 19, 16] (2) [8, 41, 5, 7] (...

[60, 0, 60, 0] (3) [30, 0, 30, 0] (3) [17, 10, 5, 10] (3) [17, 5, 5, 5] (3) [17, 0, 0, 0] (3) [8, 40, 5, 7] (2) [22, 5, 5] (2) [29, 71] (1) [14, 86] (...

1def ratio_reduce(
2    total: int, ratios: List[int], maximums: List[int], values: List[int]
3) -> List[int]:
4    """Divide an integer total in to parts based on ratios.
5
6    Args:
7        total (int): The total to divide.
8        ratios (List[int]): A list of integer ratios.
9        maximums (List[int]): List of maximums values for each slot.
10        values (List[int]): List of values
11
12    Returns:
13        List[int]: A list of integers guaranteed to sum to total.
14    """
15    ratios = [ratio if _max else 0 for ratio, _max in zip(ratios, maximums)]
16    total_ratio = sum(ratios)
17    if not total_ratio:
18        return values[:]
19    total_remaining = total
20    result: List[int] = []
21    append = result.append
22    for ratio, maximum, value in zip(ratios, maximums, values):
23        if ratio and total_ratio > 0:
24            distributed = min(maximum, round(ratio * total_remaining / total_ratio))
25            append(value - distributed)
26            total_remaining -= distributed
27            total_ratio -= ratio
28        else:
29            append(value)
30    return result
            

Path 2: 8 calls (0.15)

20 (3) 3 (2) 300 (1) 258 (1) 255 (1)

[2, 4] (5) [1, 1, 1, 1] (3)

[1, 1] (2) [3, 3] (2) [100, 100, 100, 100] (1) [86, 86, 86, 86] (1) [85, 85, 85, 85] (1) [20, 20] (1)

[5, 5] (2) [2, 2] (2) [100, 100, 100, 100] (1) [86, 86, 86, 86] (1) [85, 85, 85, 85] (1) [0, 0] (1)

[25, 25, 25, 25] (1) [22, 21, 22, 21] (1) [21, 21, 21, 22] (1) [-2, -8] (1) [4, 4] (1) [1, 1] (1) [1, 0] (1) [-1, -2] (1)

1def ratio_reduce(
2    total: int, ratios: List[int], maximums: List[int], values: List[int]
3) -> List[int]:
4    """Divide an integer total in to parts based on ratios.
5
6    Args:
7        total (int): The total to divide.
8        ratios (List[int]): A list of integer ratios.
9        maximums (List[int]): List of maximums values for each slot.
10        values (List[int]): List of values
11
12    Returns:
13        List[int]: A list of integers guaranteed to sum to total.
14    """
15    ratios = [ratio if _max else 0 for ratio, _max in zip(ratios, maximums)]
16    total_ratio = sum(ratios)
17    if not total_ratio:
18        return values[:]
19    total_remaining = total
20    result: List[int] = []
21    append = result.append
22    for ratio, maximum, value in zip(ratios, maximums, values):
23        if ratio and total_ratio > 0:
24            distributed = min(maximum, round(ratio * total_remaining / total_ratio))
25            append(value - distributed)
26            total_remaining -= distributed
27            total_ratio -= ratio
28        else:
29            append(value)
30    return result
            

Path 3: 1 calls (0.02)

3 (1)

[0, 0] (1)

[3, 3] (1)

[4, 4] (1)

[4, 4] (1)

1def ratio_reduce(
2    total: int, ratios: List[int], maximums: List[int], values: List[int]
3) -> List[int]:
4    """Divide an integer total in to parts based on ratios.
5
6    Args:
7        total (int): The total to divide.
8        ratios (List[int]): A list of integer ratios.
9        maximums (List[int]): List of maximums values for each slot.
10        values (List[int]): List of values
11
12    Returns:
13        List[int]: A list of integers guaranteed to sum to total.
14    """
15    ratios = [ratio if _max else 0 for ratio, _max in zip(ratios, maximums)]
16    total_ratio = sum(ratios)
17    if not total_ratio:
18        return values[:]
19    total_remaining = total
20    result: List[int] = []
21    append = result.append
22    for ratio, maximum, value in zip(ratios, maximums, values):
23        if ratio and total_ratio > 0:
24            distributed = min(maximum, round(ratio * total_remaining / total_ratio))
25            append(value - distributed)
26            total_remaining -= distributed
27            total_ratio -= ratio
28        else:
29            append(value)
30    return result