Skip to content

Instantly share code, notes, and snippets.

@yUtopist
Forked from scwood/largestRemainderRound.js
Last active March 27, 2021 12:40
Show Gist options
  • Save yUtopist/28743d9b2aa8729ad05ad236fa82861a to your computer and use it in GitHub Desktop.
Save yUtopist/28743d9b2aa8729ad05ad236fa82861a to your computer and use it in GitHub Desktop.
Largest remainder round
/**
* largestRemainderRound will round each number in an array to the nearest
* integer but make sure that the the sum of all the numbers still equals
* desiredTotal. Uses Largest Remainder Method. Returns numbers in order they
* came.
*
* @param {number[]} numbers - array of numbers
* @param {number} desiredTotal - denominator: 100 for %, 360 for deg
* @return {number[]} the list of rounded numbers
* @example
*
* const numbers = [15, 12, 10, 2];
* largestRemainderRound(numbers, 360)
*
* // => [ 139, 111, 92, 18 ]
*
*/
// This modification allows to pass array of not rounded numbers
// and the denominator which is a desired total of the array.
// in case if you want to round up percentages you need to pass 100
// and in case of angles you got to pass 360
const largestRemainderRound = (numbers, desiredTotal) => {
const _upperSum = numbers.reduce((a, b) => a + b)
const _sortedArray = numbers.map((number, index) => {
const _value = (number / _upperSum) * desiredTotal
return {
floor: Math.floor(_value),
remainder: Math.round((_value - Math.floor(_value)) * 10000) / 10000,
index: index
}
}).sort((a, b) => b.remainder - a.remainder)
const _lowerSum = _sortedArray.reduce((a, b) => a + b.floor, 0)
for (let i = 0; i < desiredTotal - _lowerSum; i++) {
_sortedArray[i].floor++;
}
return _sortedArray.sort((a, b) => a.index - b.index).map(e => e.floor)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment