JSFiddle - React, Tailwind, and code Playground

by Stepan Parunashvili

JavaScript

/* 
Was asked in airbnb phone screen

When you book on airbnb the total price is:

Total price = base price + service fee + cleaning fee + ...

input : array of decimals ~ X
output : array of int ~ Y

But they need to satisfy the condition:

sum(Y) = round(sum(x))
minmize (|y1-x1| + |y2-x2| + ... + |yn-xn|)
Example1:
input = 30.3, 2.4, 3.5
output = 30 2 4

Example2:
input = 30.9, 2.4, 3.9
output = 31 2 4



*/

/*
	My Idea:
  
  First, get the rounded sum -- our goal
  Then, floor all the numbers
  and get the floored sum
  sort the floored numbers by their distance
  until we reach the rounded number, increase our flooded number by one
*/

function roundNumbers(nums) {
	const goal = Math.round(nums.reduce((a, b) => a + b))
	const numsWithFloor = nums
  	.map(num => [num, Math.floor(num)])
    .sort(([numA, flo])
  
	const flooredNums = nums
		.map((val, index) => ({val, index}))
		.sort(({val: a}, {val: b}) => (b - Math.floor(b)) - (a - Math.floor(a)))
		.map(value => ({...value, val: Math.floor(value.val)}))
	const flooredSum = flooredNums.map(({val}) => val).reduce((a, b) => a + b)
	for (let i = 0; i < sum - flooredSum; i++) {
		flooredNums[i].val++
	}
	return flooredNums.sort(({index: a}, {index: b}) => a - b).map(({val}) => val)
}

console.log(roundNumbers([30.3, 2.4, 3.5]))