2
votes

I need help with array sum algorithm, sum of result array values is never greater then limit, I have provided input => output bellow

I have tried something like this but It doesn't work properly for all tests in example

input
  .map((x, i) => input
    .slice(0, i + 1)
    .reduce((prev, cur) => prev + cur, 0) > limit ? Math.max((x - (input.reduce((prev, cur) => prev + cur, 0) - limit)), 0) : x)

Example tests:

limit = 500

[0] => [0]

[300] => [300]

[600] => [500]

[0,1000] => [0, 500],

[600,300] => [500,0]

[500,0,0] => [500,0,0]

[400,200,0] => [400,100,0]

[0,200,300] => [0,200,300]

[0,600,300] => [0,500,0]

[0,0,600] => [0,0,500]

3
I made you a snippet. Please add your test cases to itmplungjan
Ah....I get it now.T.J. Crowder
Do you need the code to specifically use map, reduce, filter or can you just write a loop?Alex H
It's not required to use map, reduce,filter... thanks for helpMario Lucki

3 Answers

8
votes

You can keep track of how much you have left, and use Math.min in your map callback:

let remaining = limit;
const result = array.map(value => {
    value = Math.min(value, remaining);
    remaining -= value;
    return value;
});

Live Example:

function test(limit, array, expect) {
    let remaining = limit;
    const result = array.map(value => {
        value = Math.min(value, remaining);
        remaining -= value;
        return value;
    });
    const good = result.every((value, index) => value === expect[index]);
    console.log(array.join(","), result.join(","), good ? "OK" : "<== Error");
}

const limit = 500;
test(limit, [0], [0]);
test(limit, [300], [300]);
test(limit, [600], [500]);
test(limit, [0,1000], [0, 500]);
test(limit, [600,300], [500,0]);
test(limit, [500,0,0], [500,0,0]);
test(limit, [400,200,0], [400,100,0]);
test(limit, [0,200,300], [0,200,300]);
test(limit, [0,600,300], [0,500,0]);
test(limit, [0,0,600], [0,0,500]);
.as-console-wrapper {
    max-height: 100% !important;
}
2
votes

You need to use Math.min inside map. And decrease the limit by the number which is added to result.

const sumInLimit = (arr, limit) => {
  return arr.map(x => {
    const res = Math.min(limit, x);
    limit -= res;
    return res;
  })
}

const arrays = [
    [0],
    [300],
    [600],
    [0, 1000],
    [600, 300],
    [500, 0, 0],
    [400, 200, 0],
    [0, 200, 300],
    [0, 600, 300],
    [0, 0, 600]
]

arrays.forEach(arr => {
  console.log(JSON.stringify(arr), " => ", JSON.stringify(sumInLimit(arr, 500)))
})
0
votes

You can achieve it in this way

UPDATE: this is not elegant way, but it works

const getSumLessThanLimit = (array, limit) => array.map((value) => {
  if (limit <= 0) return 0;
  if (value <= limit) {
    limit -= value;
    return value;
  }
  if (value > limit) {
    const temp = limit;
    limit = 0;
    return temp;
  }
  return limit; 
});