Back to all solutions

#1058 - Minimize Rounding Error to Meet Target

Problem Description

Given an array of prices [p1,p2...,pn] and a target, round each price pi to Roundi(pi) so that the rounded array [Round1(p1),Round2(p2)...,Roundn(pn)] sums to the given target.

Each operation Roundi(pi) could be either Floor(pi) or Ceil(pi).

Return the string "-1" if the rounded array is impossible to sum to target. Otherwise, return the smallest rounding error, which is defined as Σ |Roundi(pi) - (pi)| for i from 1 to n, as a string with three places after the decimal.

Solution

/**
 * @param {string[]} prices
 * @param {number} target
 * @return {string}
 */
var minimizeError = function(prices, target) {
  const nums = prices.map(p => parseFloat(p));
  const floors = nums.map(n => Math.floor(n));
  const ceils = nums.map(n => Math.ceil(n));

  const minSum = floors.reduce((sum, f) => sum + f, 0);
  const maxSum = ceils.reduce((sum, c) => sum + c, 0);

  if (target < minSum || target > maxSum) {
    return '-1';
  }

  const ceilsNeeded = target - minSum;

  const items = nums.map((n, i) => ({
    floorError: n - floors[i],
    ceilError: ceils[i] - n,
    diff: (ceils[i] - n) - (n - floors[i])
  }));

  items.sort((a, b) => a.diff - b.diff);

  let totalError = 0;

  for (let i = 0; i < nums.length; i++) {
    if (i < ceilsNeeded) {
      totalError += items[i].ceilError;
    } else {
      totalError += items[i].floorError;
    }
  }

  return totalError.toFixed(3);
};