Change Cash Function Optimization - Javascript

那年仲夏 提交于 2021-02-08 09:23:58

问题


Today I come to your aid in favor of optimizing some code!

I was asked to solve a problem on a test a few weeks ago, and came up with this non-optimal solution since I'm beggining to learn Javascript.

I wonder if there's a way (of course there is) to make this better.

Here's the situation:

"I am a particular kind person who has an infinite ammount of $2, $5 and $10 dollar bills, and I'm willing to change cash for anyone who wants it, BUT in the most efficient way, with the minimum ammount of bills."

Since I had to return an object with the number of bills (or null in case of less than $2), I gave the following solution:

function giveChange(change){    
var two = 0;
var five = 0;
var ten = 0;
var changeToGo = change;

while(changeToGo >= 11){
    changeToGo -=10;
    ten+=1;
}

while(changeToGo >=7 && changeToGo <=11){
    changeToGo-=5;
    five+=1;
}

while(changeToGo >=2 && changeToGo <=6 ){
    if(changeToGo == 5){
        changeToGo -=5;
        five+=1;
}
    else{
        changeToGo -= 2;
        two+=1;
    }
}

if (change < 2){
    return null;
}

return {
    two: two,
    five: five,
    ten: ten
};
}

I think there must be a clever and more elegant solution (probably with mod% or something), but that monstrosity was what I was able to pull off at the time hahaha.

Any thoughts?


回答1:


Edit: Removed he initial answer, as it was based on a misconception about the requirements.

Ok, then let's turn that around, first let's determine how many $2 bills I'll have to hand out to get to a number that's divisible by $5 bills. So for now I only care about the rests < $5 for to calculate the $2 bills.

The generic idea is, If I have a value where change%5 is 2, like $12 or $17 or $22, ... I hand out one $2 bill and I can divide the rest by 5.

For values like $14, $19, ... it's two $2 bills, for $11, $16, ... I subtract $6, and for $13, $18, ... it's $8

With that I have a static table of how many $2 bills I'd have to hand out, for every change % 5; no loops or so needed, just a simple lookup.

function giveChange(change){
  const two = change < 4? change>>1: [0,3,1,4,2][Math.floor(change) % 5],
    rest = change - two*2;

  return { 
    two,
    five: Math.floor((rest%10)/5), 
    ten: Math.floor(rest/10), 
  };
}

Care to explain again what this does? "change>>1" and "[0,3,1,4,2][Math.floor(change) % 5];" ?

change >> 1 is here just a shorthand for Math.floor(change/2) and deals mostly with the special cases giveChange(1) and giveChange(3); They are not interchangable, but for the range 0..4 (where I use it) they produce the same result.

let two = [0,3,1,4,2][change % 5];

//does 
let two;
if(change%5 === 0) two = 0;
if(change%5 === 1) two = 3;
if(change%5 === 2) two = 1;
if(change%5 === 3) two = 4;
if(change%5 === 4) two = 2;

And Math.floor(change) % 5 is just in case that you'll use this with floats, like giveChange(25.90)

But maybe an example explains it better

for(let change=4; change<50; ++change){
  let two = [0,3,1,4,2][change%5];
  console.log("change: %i, two: %i, rest: %i", change, two, change - two*2);
}
.as-console-wrapper{top:0;max-height:100%!important}

you see how two always always has the same 5 values in the same order, and how the rest now is divisible by 5 and or 10.

That's what this code does, it looks up the Array [0,3,1,4,2], how many $2 bills it needs use for any given change, so that the rest is divisible by 5.




回答2:


The idea: when the amount is odd, add a five dollar bill. Then add two dollar bills until the remaining amount is a multiple of ten.

function giveChange(amount) {
    var ch = { two:0, five:0, ten:0 };

    if ( amount < 2 || amount == 3 ) return;

    if ( amount % 2 ) {
        amount -= 5;
        ch.five = 1;
    }   
    
    while ( amount % 10 ) {
        amount -= 2;
        ch.two ++;
    }

    ch.ten = amount/10;

    return ch;
}

console.log(giveChange(12));
console.log(giveChange(27));
console.log(giveChange(33));

You can also skip the while loop if you use Math.floor:

function giveChange(amount) {
    var ch = { two:0, five:0, ten:0 };

    if ( amount < 2 || amount == 3 ) return;

    if ( amount % 2 ) {
        amount -= 5;
        ch.five ++;
    }
  
    ch.ten = Math.floor(amount/10);

    ch.two = (amount % 10)/2;

    return ch;
}

console.log(giveChange(12));
console.log(giveChange(27));
console.log(giveChange(33));



回答3:


You could take a combination algorithm and return the denominators in an array

function combine(array, sum) {

    function c(left, right, sum) {
        if (!sum) {
            result = right;
            return true;
        }
        return left.some(function (a, i, aa) {
            return a <= sum && c(aa.slice(i + (a > sum - a)), right.concat(a), sum - a);
        });
    }

    var result = [];
    c(array.sort(function (a, b) { return b - a; }), [], sum);
    return result;
}

function giveChange(change) {
    return combine([10, 5, 2], change);
}

console.log(giveChange(7));
console.log(giveChange(13));
console.log(giveChange(23));



回答4:


here is my Solution, tested it and works fine

function caisse(cash){
two =0;
five =0;
ten = 0;

if (cash>10){
rendu = cash%10;
ten = Math.floor(cash/10);
}
if (rendu%2===0){
  two = rendu/2
}
  if (rendu%2==1 && rendu>=5)
{
  five = 1
two = (rendu-5)/2; 
}

  else if (rendu%2==1 && rendu<5){
    two=Math.floor(rendu/2);
}
return {"two :": two, "five :": five, "ten : ": ten};
}


来源:https://stackoverflow.com/questions/48914689/change-cash-function-optimization-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!