1

I'm stumbling into a problem that I've to treat a given value and check if this value is bigger than my array of values, if it is, combine the output using my array.

For example.

My array always will be:

const ArrayPrimitive = [100,50,20,10];

And for example the given value in the input:

  • Entry: 30.00 Result: [20.00, 10.00]
  • Entry: 80.00 Result: [50.00, 20.00, 10.00]
  • Entry: 125.00 Result: throw NoteUnavailableException
  • Entry: -130.00 Result: throw InvalidArgumentException
  • Entry: NULL Result: [Empty Set]

I've started to develop but I'm stuck in the in how to deal with the rest, after check if the value is valid.

const ArrayPrimitive = [100,50,20,10];
var combination = [];
$(document).ready(function(){
  $(".btn-submit").on("click",function(){
    var amountOfMoney = document.getElementById('amountOfMoney').value;
    for(let i=0; i=ArrayPrimitive.length;i++){
      if(amountOfMoney=ArrayPrimitive[i]){
        combination.push(amountOfMoney);
      }
      while(amountOfMoney > ArrayPrimitive[i]){
        var k = amountOfMoney/ArrayPrimitive[i];
        for(let j=0; j = k; j++){
          combination.push(ArrayPrimitive[i]);
          amountOfMoney = amountOfMoney - ArrayPrimitive[i];
        }
        var rest = n % ArrayPrimitive[i];
      }
    }
  });
});

My major questions are:

  1. Can you guys help me to solve this in the old way?
  2. I'm about to learn ES6 and probably the .map or other function could save my life, could someone enlighten me in this point?

I hope I made myself clear.

https://jsfiddle.net/v748ha08/1/

UPDATE: Thanks @Malk for your answer but your solution just provides the right answer only when you don't have to combine multiple values of the subset.

e.g. Entry: 200.00 Result: [100.00, 100.00]

In this case I need 2 values of 100 in my subset, and when I test this they functions throws me an error.

Yuri Pereira
  • 1,945
  • 17
  • 24
  • 1
    It seems that you want to know what combination of values from *ArrayPrimitive* will add up to the provided value. If there is no solution, throw an error. There is no "ES6", the most recent version of the language standard is ECMAScript 2017, which is the 7th edition. The *Array.prototype.map* method was introduced with ECMAScript 5.1, so is available in nearly all implementations in use. Have you seen [*How to compute the number of Bills / Coins when making change*](http://stackoverflow.com/questions/40333796/how-to-compute-the-number-of-bills-coins-when-making-change)? – RobG Jan 17 '17 at 22:37
  • 3
    One thing you could do to make this clearer is to remove the DOM stuff and concentrate on the algorithm. For instance, instead of the document.ready, submit click and getElementById stuff, just set amountOfMoney to one of the values you want to check, and run the code after it. This is part of narrowing the problem down to the minimum needed to show the problem you are having (more on that at [mcve]). Otherwise, it's not entirely clear what your requirements are. – Heretic Monkey Jan 17 '17 at 22:39
  • What should happen if input is 90, or 40, or 35, or...? Could you explain more... – sinisake Jan 17 '17 at 23:02
  • @RobG a lot of us still call ES2015 "ES6" - old habits die hard – Alnitak Jan 17 '17 at 23:03
  • As a matter of design, I would avoid using exceptions as a way to handle failure in this case--instead return `null` or something. Anyway, your question is quite unclear. You seem to want to find the subset of the array adding up to some desired number, but that is not stated well in the question (or title). In any case, this is a well-known problem called the "subset sum" problem, which you can google. –  Jan 18 '17 at 01:40
  • @Alnitak—I'm not a huge fan of the current naming scheme, it is what it is. ;-) – RobG Jan 18 '17 at 03:33

1 Answers1

2

If you want to iterate through an array and build up an object (or anything else) along the way then Array.reduce() is the way to go.

const ArrayPrimitive = [100, 95, 20, 10]; // Assuming presorted array(descending)

function findChange(m) {
  return ArrayPrimitive.reduce((mm, c) => {
    if (mm.rest >= c) {
      mm.change.push(c);
      mm.rest -= c
    }
    return mm
  }, {
    change: [],
    rest: m
  });
}

function findChangeOld(m) {
  var retval = {
      change: [],
      rest: m
    },
    i = ArrayPrimitive.length;

  for (var x = 0; x < i; x++) {
    if (retval.rest >= ArrayPrimitive[x]) {
      retval.change.push(ArrayPrimitive[x])
      retval.rest -= ArrayPrimitive[x];
    }
  }
  return retval;
}

function calcChange(v) {
  var c = findChangeOld(v);

  if (v < 0 || isNaN(v)) {
    console.log(`${v}: throw InvalidArgumentException`);
    return;
  }

  if (c.rest > 0)
    console.log(`${v}: throw NoteUnavailableException`);
  else
    console.log(`${v}: ${c.change}`);
}

calcChange(30);
calcChange(80);
calcChange(105);
calcChange(125);
calcChange(-130);
calcChange(null);
Malk
  • 11,855
  • 4
  • 33
  • 32
  • wow, you've made that complicated... – Alnitak Jan 17 '17 at 23:04
  • But with the updated data in the shippet (rollback if you prefer), `105` fails, even though it should solve with `95,10`. –  Jan 18 '17 at 01:35
  • Posting code–only answers isn't that helpful, especially when they are so different from the OP. You need to explain what was wrong with the OP's code and the logic of your replacement. For example, given a value of 100, the result could be 1x100, 5x20 or 10x10. There may also be cases where you must use multiples of smaller values rather than always selecting the largest possible, e.g. to me 105 should return 95, 10 not throw an exception. – RobG Jan 18 '17 at 03:38
  • @robG In my case 105 should throw an error because there's no combination of the ArrayPrimitive[100,50,20,10] that result in modulus zero. – Yuri Pereira Jan 18 '17 at 14:05
  • RobG, I agree with you about code-only answers. But sometimes a question is unclear, and not everyone speaks english. Odds are, we both speak code. Instead of asking my questions; I posted an answer that included several assumptions more to let OP build off it and show us how it doesn't fit their question than to provide a definitive answer. – Malk Jan 18 '17 at 16:43
  • 1
    Answers aren't just for the OP, they're supposed to be for anyone with a similar problem. And code only says exactly what it's doing, it doesn't explain the underlying logic or why something is being done. Your *ArrayPrimitive* has different values to the OP so now we still don't know if you've produced the correct result for 105 given your values not the ones in the OP. I'm not criticising you for having a go, just trying to get clarification on the answer. – RobG Jan 18 '17 at 23:40
  • Maybe they can add code snippets to comments. You're looking for clarification on the answer, I'm still looking for clarification on the problem. BTW my ArrayPrimitive was not what is seen here. Someone edited it. – Malk Jan 19 '17 at 18:44