Find minimum and maximum sum based on rule

Problem : Given five positive integers, find the minimum and maximum values that can be calculated by summing exactly four of the five integers. Then return an array which has the minimum and maximum sum as elements.

Example : array = [1,2,3,4,5] would have minimum sum 1+2+3+4 = 10
and maximum sum 2+3+4+5 = 14

Hence, function returns [10 , 14]

This is my attempt so far. I thought .filter would be great for solving this but it’s not working. Someone please inspect and find the error

function miniMaxSum(arr) {
    var max = Math.max(...arr)
    var min = Math.min(...arr)

    var filteredForMax = arr.filter(el => el > min)
    
    var sumMax = 0;
    for (var i = 0; i < filteredForMax.length; i++) {
        sumMax = sumMax + filteredForMax[i];
    }

    var filteredForMin = arr.filter(el => el < max) 

    var sumMin = 0;
    for (var j = 0; j < filteredForMin.length; j++) {
        sumMin = sumMin + filteredForMin[j];
    }

return [sumMin, sumMax]

Well, it’s returning [10, 14] for me (assuming I add a closing curly brace to close out the function), so it’s basically working.

But in coding you have to consider “edge cases”, things that might make your code fail. For example, what would happen if you gave it [1, 1, 1, 1, 1]?

I see where you’re going with filter, and there’s probably a way to make that work, but to be honest sort was the first thing to pop into my mind. See what you can do with that hint.

1 Like

Using the below, my output is NaN 14

Could you kindly advise on why minSum is displaying NaN for the below?

Thank you for your suggestion on using .sort.

I assume by using .sort one can add a callback function to not include the smallest or biggest number as needed for the problem?


function minMaxSum (arr) {

  var min = Math.min(...arr)
  var max = Math.max(...arr)

  var maxFilter = arr.filter(el=>el>min)
  var minFilter = arr.filter(el=>el<max)

  var maxSum = 0;
  var minSum = 0;

  for (var i = 0 ; i<maxFilter.length ; i++) {
    maxSum = maxSum + maxFilter[i]
  }

  for (var j = 0 ; j<minFilter.length ; j++) {
    minSum = minSum + minFilter[i]
  }

  return minSum + " " + maxSum
}

var array = [1,2,3,4,5]

console.log(minMaxSum(array))

You made a simple typo. I could tell you, but you really should learn how to find theses. These are very common, but learning to debug is an important skill. There will always be bugs so an expert coder is also and expert debugger. I would start by putting console.log statements along the line and see where the data is getting corrupted. And once you find that typo, do you understand why it’s causing a NaN?

But ultimately, ultimately, I still think your algorithm is flawed because it will fail for some cases, like the one I gave before.

Using sort is an option. If we do that? Where are the min and max elements? What are the arrays containing the leftover amounts? That is one way to solve it.

Or, you can do it without the sort.n You get the min and max elements before you start. What if you got the total sum of all the elements. What would be the relationship of the allSum to the maxSum that you want?

I really think the filter method is flawed. It’s fixable, but not without making things more complex. For example, I just did the sort implementation in three lines. I’m not saying that to make you feel bad (these things take a long time to get good at.) I’m just pointing out that there exists and easier way. Part of getting good at algorithms is being able to keep an open mind, seeing lots of possible ways and learning an instinct for which is best. I think the sort solution is a three line solution (inside the function) and the “find the min and max first” might be a four line solution, but might be a bit faster. See if you can figure them out - then you’d really be getting an understanding.

Sorry to string you along, but this will really help you see what you need to learn.

One last thought - you are summing the arrays with a for loop. Like filter and sort, there is an array method called reduce - that would be a sexier way to sum an array.

I have tried debugging by myself before asking.

console.log for min and max filter shows results as intended i.e.

maxFilter = [2,3,4,5]
minFilter = [1,2,3,4]

NaN starts showing when the for loop is applied to minFilter

However from where I see it, there is no typo from my perspective. The minFilter for loop is identical to the maxFIlter for loop except var j is used as a counter and global variable minSum is added instead.

What variable are you using inside the minSum loop to iterate the minFilter indexes?

Then why not start console.loging out inside the for loop? Keep narrowing it down until you find where the problem starts, where the data diverges from what you expect. When you do that, the problem will be obvious. This is a very important skill to learn, to learn to think this way.

1 Like

Epic fail! Should be [ j ] instead of [ i ]

Oh well. One step of a time learning is. Thanks both!

1 Like

It’s often the little things that get you. a forgotten {, an extra ), or just simple misspellings.

Although your solution does now seem to work, consider the problem parameters wanted you to return an array. What are you returning? Also, @kevinSmith is absolutely right about filter here. Try using your solution but passing in [1,1,1,1,1] what happens?

Also, while my initial instinct was using Array.sort(), Math.max() and Math.min() is actually quite clever and can lead to a really simple, clean solution.

One more thing: While there are exceptions, for the most part you want to minimize the moving parts. the more layers of variables you use, the more chance there is for bugs and typos to work their way in.

But the sort gives you min and max. I think both ways are good solutions. Using sort would be O(n log n) and finding min and max first gives an O(n) solution. And really, we could get min and max with one pass.

But they’re both cromulent solutions.

lol. It’s funny, in my sort solution, I was reducing twice (using Array.slice()) But you are right. With sort you can use the same logic from Math.min/max and thus only reduce once. Ending up with a two line solution.

Got there in the end

function miniMaxSum(arr) {

        var sorted = arr.sort();

        var maxArray = sorted.slice(1, 5)
        var minArray = sorted.slice(0, 4)

        var maxSum = 0;
        var minSum = 0;

        for (var i = 0; i < maxArray.length; i++) {
            maxSum = maxSum + maxArray[i]
        }

        for (var j = 0; j < minArray.length; j++) {
            minSum = minSum + minArray[j]
        }
      
     return minSum + " " + maxSum

what are you returning out of your miniMaxSum() function?

I’ve now changed the code to reflect this.

I used console.log before because this was required with the website I was using to input the code too. I copied and pasted it and forgot to change it back to return

Oh. Gotcha. All good then. Although you are still returning a string. didn’t the problem require you to return an array?

OK, that seems to work. But it will fail for many double digit numbers. By default, sort works by converting to a string so things get weird when you’re comparing numbers. It’s easy to fix with a callback to override the default comparison method. Do a little research. This is a good learning moment.

I still think it could be simpler. You really need to do one sum. If you know the min and max, you can use the min and max to get the two sums with simple subtraction.

Part of what employers will look for is that you know how to think about what the “best” solutions are.

And I still say that rather than summing with a for loop, you should use reduce - it is cleaner and will impress employers more. You already know filter and sort.

You did it with the sort. Can you do it without? You can find the min and max (like you did before), do one sum and then do a little math. Whenever possible, try to understand more than one solution and understand which is better in terms of speed, memory, and readability.

1 Like