0

I have been trying to come up with a solution for this algorithm for 3-4 days but nothing seems to work and the available solutions are a bit more advanced for me. It has to be solved with conditionals only so no recursion or dynamic programming.

I need to determine the least amount of coins necessary to give change given the following denominations: 1, 0.5, 0.2, 0.1, 0.05, 0.02 and 0.01.

Input is the following:

Price of an item

Sum paid by customer

Current ideas:

let price = +gets();
let paidSum = +gets();
//gets is used to accept number input
let change = paidSum - price;

I figured I could use Math.floor to isolate the integer part and subtract it but then I have no idea what to do with the remaining sum.

Would modulo work to test whether the remaining sum contains any of the remaining values for change and then subtract again until I reach zero?

I do realize this isn't the best formulated question but I am at a loss here and I've done every other task apart from this. Thanks.

  • 1
    Do you mean this one: https://en.wikipedia.org/wiki/Change-making_problem? If yes, then it should be solved by dynamical programming, greedy algorithm doesn't work. I believe that this algorithm has been described many times on SO and other websites. – Yeldar Kurmangaliyev Dec 09 '18 at 18:09
  • 1
    *"It has to be solved with conditionals only so no recursion or dynamic programming."*: why? – trincot Dec 09 '18 at 18:14
  • Should the algorithm return a number or the list of coins? – trincot Dec 09 '18 at 18:20
  • The list of coins. For example, let's say price is 0.99 and customer payment is 4.00. Change: 3,01: Expected return is: 3 x 1 and 1 x 0.01 –  Dec 09 '18 at 18:31

3 Answers3

5

Simpler, reverse and map the denominations in cents and return a new array with the number of coins you need for each denomination.

const coinsCents = [1, 2, 5, 10, 20, 50, 100]
const getChange = (amountInCents) => {
    return coinsCents.reverse().map(coin => {
        let amountCoin = Math.floor(amountInCents/coin)
        amountInCents -= amountCoin * coin
        return amountCoin
    }).reverse()
}
Manuel del Pozo
  • 155
  • 2
  • 3
3

With the denominations you have specified, the problem is simpler than the general change making problem. In this actual case we can be sure that using the largest denomination, that is not greater than the amount to pay, always leads to an optimal solution.

So then there is no need for recursion or dynamic programming. Just a simple loop will do.

I will here ignore the additional "layer" of getting the price of the bill and the amount that the customer pays. In the end the only thing that counts is the change amount to pay back to the customer. So this snippet asks for that change amount and returns the coins that need to be given as change.

function getChange(amount) {
    amount *= 100; // Convert to number of cents
    var denominations = [1, 2, 5, 10, 20, 50, 100]; // cents
    var result = [];
    while (amount > 0) {
        var coin = denominations.pop(); // Get next greatest coin
        var count = Math.floor(amount/coin); // See how many times I need that coin
        amount -= count * coin; // Reduce the amount with that number of coins
        if (count) result.push([coin/100, count]); // Store count & coin
    }
    return result;
}

// I/O management

change.oninput = function () {
    var coins = getChange(this.value);
    result.textContent = coins.map(([coin, count]) => `${count} x $${coin}`).join(" + ");
};
To be paid to customer: <input id="change">
<div>Coins to pay: <span id="result"></span></div>
trincot
  • 317,000
  • 35
  • 244
  • 286
0
var coins;
var coinArray = {};
var output = {};


/* Method to get coin value without decimal point - it is required because 
* javascript will consider 5.6 as 6 if we do Math.round()
*/
function getRoundFigureCoinValue(x) {
    return (x * 10 - ((x * 10) % 10)) / 10;
}

// Method to calculate possible combination of coins
function calculateCoins(input) {
    let largestPossibleCoin = 1;

    if (input) {
        coins.forEach((x) => {
            if (input >= x) {
                largestPossibleCoin = x;
            }
        });
        let remainingCents = input % largestPossibleCoin;
        output[largestPossibleCoin] = getRoundFigureCoinValue(
            (input / largestPossibleCoin).toFixed(1)
        );
        if (remainingCents && input > 1) {
            calculateCoins(remainingCents);
        }

        return largestPossibleCoin;
    }
}

// Method to be called to get output.
function calculatePossibleCoinCombinations(value) {
    if (isNaN(value) || +value <= 0) {
        console.log('Invalid input');
        return;
    } else {
        console.log('Possible combinations are:')
        value = +value;
    }

    coins = [1, 5, 10, 25];
    while (coins.length) {
        let largestPossibleCoin = calculateCoins(value) || 0;
        let outputString = '';
        coins = coins.filter((x) => x < largestPossibleCoin);
        Object.keys(output).forEach((key) => {
            outputString += `${output[key]} - ${key} cents; `;
        })
        console.log(outputString);
        output = {};
    }
}


/*
Sample inputs:
 calculatePossibleCoinCombinations('89');
 calculatePossibleCoinCombinations(10);
 calculatePossibleCoinCombinations(0);
 calculatePossibleCoinCombinations('someString');
 calculatePossibleCoinCombinations(-10)
*/
Sreeketh K
  • 21
  • 4