Last active
March 2, 2020 10:09
-
-
Save filiph/cea429a0404f3a23f69c to your computer and use it in GitHub Desktop.
Google Apps Script custom function (https://developers.google.com/apps-script/guides/sheets/functions) that takes an integer count and a partition (array of percentages that sum to 1.0) and distributes the count according to the partition. Returns an array of integers (the restricted weighted integer composition). Works well for very small value…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Takes [count] of items and the [partition] (array of percentages) to | |
// distribute against. Returns an array of integers that sums to [count]: | |
// an integer composition weighted by the partition. | |
// | |
// We don't use the Bresenham algorithm because it doesn't provide the best | |
// results for low values of [count]. | |
function DISTRIBUTE(count, partition) { | |
// Custom function in Apps Script takes a 2D array. We're only interested in | |
// the first row. | |
partition = partition[0]; | |
// First, distribute rounded down, but keep the remainders for each bin. | |
var result = []; | |
var remainders = []; | |
var alreadyDistributedCount = 0; | |
for (var i = 0; i < partition.length; i++) { | |
var currentCount = Math.floor(partition[i] * count); | |
var remainder = partition[i] * count - currentCount; | |
result.push(currentCount); | |
remainders.push(remainder); | |
alreadyDistributedCount += currentCount; | |
} | |
// Now iteratively add [partition] values to corresponding remainders. | |
var j = 0; | |
while (alreadyDistributedCount < count) { | |
remainders[j] += partition[j]; | |
if (remainders[j] > 1) { | |
result[j] += 1; | |
remainders[j] -= 1; | |
alreadyDistributedCount += 1; | |
} | |
j += 1; | |
if (j >= partition.length) j = 0; | |
} | |
// Apps Script expects 2D array output. We only provide one row. | |
return [result]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment