splitByLargestRemainder function
Splits size cells across weights using Largest Remainder Method.
The return values always sum to size and each segment receives:
- floor(size * weight / totalWeight) cells initially
- remaining cells distributed by descending fractional remainder
If multiple segments have equal remainder, ties prefer the segment that had more cells on the previous frame for stable rendering across repeated layouts.
Implementation
List<int> splitByLargestRemainder(
int size,
List<int> weights, {
List<int> previous = const [],
}) {
final result = List<int>.filled(weights.length, 0);
if (size <= 0 || weights.isEmpty) return result;
var totalWeight = 0;
final normalizedWeights = List<int>.filled(weights.length, 0);
for (var i = 0; i < weights.length; i++) {
final weight = weights[i];
final clampedWeight = weight < 0 ? 0 : weight;
normalizedWeights[i] = clampedWeight;
totalWeight += clampedWeight;
}
if (totalWeight <= 0) return result;
var floorSum = 0;
final candidates = <_LargestRemainderCandidate>[];
for (var i = 0; i < normalizedWeights.length; i++) {
final weighted = size * normalizedWeights[i];
final base = weighted ~/ totalWeight;
final remainder = weighted % totalWeight;
result[i] = base;
floorSum += base;
final previousShare = i < previous.length ? previous[i] : 0;
candidates.add(_LargestRemainderCandidate(i, remainder, previousShare));
}
var remaining = size - floorSum;
if (remaining <= 0) return result;
candidates.sort((a, b) {
if (a.remainder != b.remainder) return b.remainder - a.remainder;
if (a.previous != b.previous) return b.previous - a.previous;
return a.index - b.index;
});
for (var i = 0; i < remaining; i++) {
result[candidates[i].index]++;
}
return result;
}