testsAndMisc/PYTHON/split/split_x_into_n_symmetrically.py
Krzysztof kuhy Rudnicki f6d3ae0c7e Enable D100-D107 docstring rules: add docstrings to all modules, classes, methods, and functions
- Added module docstrings to 19 Python files
- Added class docstrings to 5 classes (ScreenLocker, PokerModifierApp, etc.)
- Added method docstrings to 22 methods
- Added function docstrings to 25 functions
- Added __init__ docstrings to 5 classes
- Removed D100-D107 from ruff ignore list (docstrings now enforced)
- Removed deprecated ANN101, ANN102, UP038 rules from ignore list
- Fixed UP038: use union types in isinstance() calls
- All ruff checks now pass with full docstring enforcement
2025-11-30 14:45:55 +01:00

60 lines
1.9 KiB
Python

"""Distribute values symmetrically across N parts."""
def calculate_symmetric_weights(N, middle_weight, factors=None):
"""Calculate symmetric weights for both even and odd N.
N: Number in which to split.
middle_weight: The middle value for symmetry.
factors: If provided, controls the difference in weights (used for the
`split_x_into_n_symmetrically` function).
Must have length N // 2 or N // 2 - 1 depending on N.
"""
half_N = N // 2
weights_left = [middle_weight]
if factors:
for factor in factors:
next_weight = weights_left[-1] + factor
weights_left.append(next_weight)
else:
for i in range(half_N - 1):
weights_left.append(middle_weight - (i + 1))
if N % 2 == 0:
weights = weights_left[::-1] + weights_left
else:
weights = [*weights_left[::-1], middle_weight, *weights_left]
return weights
def scale_to_total(X, weights):
"""Scale the weights so that their sum is proportional to X.
X: Total value to distribute.
weights: The list of weights to be scaled.
"""
total_weight = sum(weights)
base_unit = X / total_weight
return [base_unit * weight for weight in weights]
def split_x_into_n_symmetrically(X, N, factors):
"""X: Total value to distribute.
N: Number in which we split.
factors: List controlling the difference in weights between consecutive days.
Must have length of N // 2 (if N is odd) or (N // 2 - 1) (if N is even).
"""
weights = calculate_symmetric_weights(N, middle_weight=1, factors=factors)
return scale_to_total(X, weights)
def split_x_into_n_middle(X, N, middle_value):
"""X: Total value to distribute.
N: Number in which we split.
middle_value: Value of the middle number (the biggest weight).
"""
weights = calculate_symmetric_weights(N, middle_weight=middle_value)
return scale_to_total(X, weights)