Find the least number of coins required that can make any change from 1 to 99 cents

后端 未结 27 2008
生来不讨喜
生来不讨喜 2020-12-07 10:08

Recently I challenged my co-worker to write an algorithm to solve this problem:

Find the least number of coins required that can make any change from

相关标签:
27条回答
  • 2020-12-07 10:20
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.Scanner;
    
    public class LeastNumofCoins 
    {
    
    
        public int getNumofCoins(int amount)
            {
                int denominations[]={50,25,10,5,2,1};
                int numOfCoins=0;
                int index=0;
                while(amount>0)
                {
                    int coin=denominations[index];
                     if(coin==amount)
                     {
                         numOfCoins++;
                         break;
                     }
                    if(coin<=amount)
                        {
                            amount=amount-coin;
                            numOfCoins++;
                        }
                        else
                        {
                            index++;
                        }
    
                }
                return numOfCoins;
        }
        public static void main(String[] args) throws IOException 
        {
    
              Scanner scanner= new Scanner(new InputStreamReader(System.in));
              System.out.println("Enter the Amount:");
              int amoount=scanner.nextInt();
              System.out.println("Number of minimum coins required to make "+ amoount +" is "+new LeastNumofCoins().getNumofCoins(amoount));
              scanner.close();
        }
    }
    
    0 讨论(0)
  • 2020-12-07 10:23

    The task

    Find the least number of coins required, that can make any change from 1 to 99 cent.
    

    differs from the task

    For each single change from 1 to 99 cent, find the least number of coins required.
    

    because the solution might be a complete different multiset of coins.

    Suppose you have not (1), (5), (10), and (25) cent coins, but (1), (3), (5), and (17) cent coins: To make the change for 5, you only need one (5) coin; but for all changes from 1 to 5 you need two (1) coins and one (3) coin, not any (5) coin.

    The greedy algorithm iterates from the smallest value to the largest, concerning the change values and coin values:

    With 1x(1) you get all change values below 2.
    
    To make a change of 2, you need an additional coin,
    which could have any value up to 2;
    choose greedy -> choose the largest -> (1).
    
    With 2x(1) you get all change values below 3.
    
    To make a change of 3, you need an additional coin,
    which could have any value up to 3;
    choose greedy -> choose the largest -> (3).
    
    With 2x(1)+1x(3) you get all change values below 6.
    
    To make a change of 6, you need an additional coin,
    which could have any value up to 6;
    choose greedy -> choose the largest -> (5).
    
    and so on...
    

    That is in Haskell:

    coinsforchange [1,3,5,17] 99
    where
        coinsforchange coins change = 
            let f (coinssofar::[Int],sumsofar::Int) (largestcoin::Int,wanttogoto::Int) = 
                    let coincount=(max 0 (wanttogoto-sumsofar+largestcoin-1))`div`largestcoin
                     in (replicate coincount largestcoin++coinssofar,sumsofar+coincount*largestcoin)
             in foldl f ([],0) $ zip coins $ tail [c-1|c<-coins] ++ [change]
    

    And in C++:

    void f(std::map<unsigned,int> &coinssofar,int &sumsofar, unsigned largestcoin, int wanttogoto)
    {
        int x = wanttogoto - sumsofar + largestcoin - 1;
        coinssofar[largestcoin] = (x>0) ? (x / largestcoin) : 0;
        //returns coinssofar and sumsofar;
    }
    std::map<unsigned,int> coinsforchange(const std::list<unsigned> &coins, int change)
    {
        std::map<unsigned,int> coinssofar;
        int sumsofar=0;
        std::list<unsigned>::const_iterator coin = coins.begin();
        unsigned largestcoin = *coin;
        for( ++coin ; coin!=coins.end() ; largestcoin=*(coin++))
            f(coinssofar,sumsofar,largestcoin,(*coin) - 1);
        f(coinssofar,sumsofar,largestcoin,change);
        return coinssofar;
    }
    
    0 讨论(0)
  • 2020-12-07 10:23

    As I understood if you are using standard currency system values then its super easy to count the minimum number of coins just by a single loop. Just always consume the max coin value and if it not possible check for the next option. But if you have a system like you have coins such as 1,2,3,4 then its not working. I guess the whole idea of having coins as 1,2,5,10,25 is to make computation easy for humans.

    0 讨论(0)
  • 2020-12-07 10:24

    On the one hand, this has been answered. On the other hand, most of the answers require many lines of code. This Python answer does not require many lines of code, merely many lines of thought ^_^ :

    div_round_up = lambda a, b: a // b if a % b == 0 else a // b + 1
    
    def optimum_change(*coins):
        wallet = [0 for i in range(0, len(coins) - 1)]
        for j in range(0, len(wallet)):
            target = coins[j + 1] - 1 
            target -= sum(wallet[i] * coins[i] for i in range(0, j))
            wallet[j] = max(0, div_round_up(target, coins[j]))
        return wallet
    
    optimum_change(1, 5, 10, 25, 100)
    #  [4, 1, 2, 3]
    

    This is a very simple rescaling algorithm that may perhaps break for inputs which I haven't considered yet, but I think it should be robust. It basically says, "to add a new coin type to the wallet, peek at the next coin type N, then add the amount of new coins necessary to make target = N - 1." It calculates that you need at least ceil((target - wallet_value)/coin_value) to do so, and does not check if this will also make every number in between. Notice that the syntax encodes the "from 0 to 99 cents" by appending the final number "100" since that yields the appropriate final target.

    The reason it does not check is something like, "if it can, it automatically will." Put more directly, once you do this step for a penny (value 1), the algorithm can "break" a nickel (value 5) into any subinterval 0 - 4. Once you do it for a nickel, the algorithm can now "break" a dime (value 10). And so on.

    Of course, it does not require those particular inputs; you can use strange currencies too:

    >>> optimum_change(1, 4, 7, 8, 100)
    [3, 1, 0, 12]
    

    Notice how it automatically ignores the 7 coin because it knows it can already "break" 8's with the change it has.

    0 讨论(0)
  • 2020-12-07 10:26

    Nice Question. This is the logic I came up with. Tested with few scenarios including 25.

    class Program
    {
    
        //Allowable denominations
        const int penny = 1;
        const int nickel = 5;
        const int dime = 10;
        const int quarter = 25;
    
        const int maxCurrencyLevelForTest =55; //1-n where n<=99
    
        static void Main(string[] args)
        {         
            int minPenniesNeeded = 0;
            int minNickelsNeeded = 0; 
            int minDimesNeeded = 0; 
            int minQuartersNeeded = 0;
    
    
            if (maxCurrencyLevelForTest == penny)
            {
                minPenniesNeeded = 1;
            }
            else if (maxCurrencyLevelForTest < nickel)
            {
                minPenniesNeeded = MinCountNeeded(penny, maxCurrencyLevelForTest);                
            }
            else if (maxCurrencyLevelForTest < dime)
            {
                minPenniesNeeded = MinCountNeeded(penny, nickel - 1);
                minNickelsNeeded = MinCountNeeded(nickel, maxCurrencyLevelForTest);                
            }
            else if (maxCurrencyLevelForTest < quarter)
            {
                minPenniesNeeded = MinCountNeeded(penny, nickel - 1);
                minNickelsNeeded = MinCountNeeded(nickel, dime - 1);
                minDimesNeeded = MinCountNeeded(dime, maxCurrencyLevelForTest);
            }
            else
            {
                minPenniesNeeded = MinCountNeeded(penny, nickel - 1);
                minNickelsNeeded = MinCountNeeded(nickel, dime - 1);
                minDimesNeeded = MinCountNeeded(dime, quarter - 1);
    
                var maxPossilbleValueWithoutQuarters = (minPenniesNeeded * penny + minNickelsNeeded * nickel + minDimesNeeded * dime);
                if (maxCurrencyLevelForTest > maxPossilbleValueWithoutQuarters)
                {               
                    minQuartersNeeded = (((maxCurrencyLevelForTest - maxPossilbleValueWithoutQuarters)-1) / quarter) + 1;
                }
            }
    
    
            var minCoinsNeeded = minPenniesNeeded + minNickelsNeeded+minDimesNeeded+minQuartersNeeded;
    
            Console.WriteLine(String.Format("Min Number of coins needed: {0}", minCoinsNeeded));
            Console.WriteLine(String.Format("Penny: {0} needed", minPenniesNeeded));
            Console.WriteLine(String.Format("Nickels: {0} needed", minNickelsNeeded));
            Console.WriteLine(String.Format("Dimes: {0} needed", minDimesNeeded));
            Console.WriteLine(String.Format("Quarters: {0} needed", minQuartersNeeded));
            Console.ReadLine();
        }
    
        private static int MinCountNeeded(int denomination, int upperRange)
        {
            int remainder;
            return System.Math.DivRem(upperRange, denomination,out remainder);
        }
    }
    

    Some results: When maxCurrencyLevelForTest = 25

    Min Number of coins needed: 7
    Penny: 4 needed
    Nickels: 1 needed
    Dimes: 2 needed
    Quarters: 0 needed
    

    When maxCurrencyLevelForTest = 99

    Min Number of coins needed: 10
    Penny: 4 needed
    Nickels: 1 needed
    Dimes: 2 needed
    Quarters: 3 needed
    

    maxCurrencyLevelForTest : 54

    Min Number of coins needed: 8
    Penny: 4 needed
    Nickels: 1 needed
    Dimes: 2 needed
    Quarters: 1 needed
    

    maxCurrencyLevelForTest : 55

    Min Number of coins needed: 9
    Penny: 4 needed
    Nickels: 1 needed
    Dimes: 2 needed
    Quarters: 2 needed
    

    maxCurrencyLevelForTest : 79

    Min Number of coins needed: 9
    Penny: 4 needed
    Nickels: 1 needed
    Dimes: 2 needed
    Quarters: 2 needed
    

    maxCurrencyLevelForTest : 85

    Min Number of coins needed: 10
    Penny: 4 needed
    Nickels: 1 needed
    Dimes: 2 needed
    Quarters: 3 needed
    

    The code can further be refactored I guess.

    0 讨论(0)
  • 2020-12-07 10:26

    After failing to find a good solution to this type of problem in PHP, I developed this function.

    It takes any amount of money (up to $999.99) and returns an array of the minimum number of each bill / coin required to get to that value.

    It first converts the value to an int in pennies (for some reason I would get errors at the very end when using standard float values).

    The returned denominations are also in pennies (ie: 5000 = $50, 100 = $1, etc).

    function makeChange($val)
    {
        $amountOfMoney = intval($val*100);
        $cashInPennies = array(10000,5000,2000,1000,500,100,25,10,5,1);
        $outputArray = array();
        $currentSum = 0;
        $currentDenom = 0;
    
        while ($currentSum < $amountOfMoney) {
            if( ( $currentSum + $cashInPennies[$currentDenom] ) <= $amountOfMoney  ) {
                $currentSum = $currentSum + $cashInPennies[$currentDenom];
                $outputArray[$cashInPennies[$currentDenom]]++;
            } else {
                $currentDenom++;
            }
        }
    
        return $outputArray;
    
    }
    
    $change = 56.93;
    $output = makeChange($change);
    
    print_r($output);
    echo "<br>Total number of bills & coins: ".array_sum($output);
    
    === OUTPUT ===
    
    Array ( [5000] => 1 [500] => 1 [100] => 1 [25] => 3 [10] => 1 [5] => 1 [1] => 3 ) 
    Total number of bills & coins: 11
    
    0 讨论(0)
提交回复
热议问题