Skip to content
Advertisement

Ways to get sum of two lowest positive integers (JS debugging failure)

I was doing this Codewar challenge of getting sum of two smallest integer.

so I was trying to solve with this:

function sumTwoSmallestNumbers(numbers) {  
    const m = numbers.sort( (a, b) => a - b )[2];   
    const a = numbers.filter(v => v < numbers.sort( (a, b) => a - b )[2]);
    const b = a.reduce( (acc, n) => acc + n);
    return b
};

It works, and later on I feel that const m is redundant, so I commented the whole const m line and then it doesn’t work now, by “doesn’t work” I mean it’s giving incorrect outcome, not typeErrors.

My question is, how is that possible??

I mean on const a I literally rewrote what const m was referring to.

How is deleting something that is repeated affects the outcome?

Thanks in advance, I appreciate your time.

Advertisement

Answer

Simply, it is because the function Array.prototype.sort in javascript modifies the actual contents of the same instance of the array as well as returns the reference to the same array, In other words, it does not return a new array with the modified contents, it modifies the same array. That’s why it doesn’t work when you remove the line :

const m = numbers.sort( (a, b) => a - b )[2];

But, why doesn’t it work when you tried to put the same logic with the next line of code?

const a = numbers.filter(v => v < numbers.sort( (a, b) => a - b )[2]);

The issue happens when the smallest value of the array is at an index larger than 2, for example:

[ 15, 28, 4, 2, 43 ]

when we try to execute the code on this array, lets take it a step by step to catch where it gets wrong.

function sumTwoSmallestNumbers(numbers) {  
    const a = numbers.filter(v => v < numbers.sort( (a, b) => a - b )[2]);
    const b = a.reduce( (acc, n) => acc + n);
    return b
};
const arr = [ 15, 28, 4, 2, 43 ]
const result = sumTwoSmallestNumbers(arr)
console.log(result)

When executing the previous code, the first thing the function will do is the filtering. It will iterate through the elements of the array:

  • Starting from index 0 => arr[0] = 15

    Testing the condition: 15 < numbers.sort( (a, b) => a - b )[2] => (15 < 15) => false

Notice! as I explained earlier, that the function sort will change the actual array rather than generating a new one, that means that when attempting to test the condition the first time, the array will be sorted, which means that if it is not already sorted, the order of its elements will defiantly change, which is a bad thing considering that the change happened during an ongoing loop through the arrays elements.

Before continuing the iteration of filter, let’s make it clear that the new order of the array after the sorting has been executed when attempting to check the condition is as follows:

[ 2, 4, 15, 28, 43 ]
  • Index 1 => arr[1] = 4

    Testing the condition: 4 < numbers.sort( (a, b) => a - b )[2] => (4 < 15) => true

  • Index 2 => arr[2] = 15

    Testing the condition: 15 < numbers.sort( (a, b) => a - b )[2] => (15 < 15) => false

  • … The rest of the elements

Conclusion

As you can notice, the value 15 has been checked twice, and the value 2, has not been checked at all, which is because of the sudden change in the order of the array during the currently ongoing iteration of the filter method. Which has lead to placing the value of 2 in an already checked location, and the value of 15 into a location that has not been checked yet.

! Notice This is not an optimal solution to such a problem, it does too much work to get to the solution, (filtering, sorting, reducing), which are expensive operations to execute. A better solution will be something like this, which involves a single loop through the elements of the array O(n):

function sumTwoSmallestNumbers(numbers) {  
  let lowest = Math.min(numbers[0], numbers[1]), 
      secondLowest = Math.max(numbers[0], numbers[1])
  for(let i = 2; i < numbers.length; i++){
    if(numbers[i] < lowest){
      secondLowest = lowest
      lowest = numbers[i]
    }else if(numbers[i] < secondLowest)
      secondLowest = numbers[i]
    else continue
  }
  return lowest + secondLowest
}
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement