public static uint CountWaysToMakeChange(this Money money, params Denomination[] denominations)
        {
            Positive.Amounts.AssertArgument(nameof(money), money.Amount);
            Guard.AgainstNullArgument(nameof(denominations), denominations);

            long     n = money.MinorIntegralAmount;
            int      m = denominations.Length;
            Currency operationCurrency = money.GetCurrency();

            long[] integralDenominations = denominations
                                           .Select(d => IntegralDenomination.CalculateAmount(d, operationCurrency))
                                           .ToArray();

            // table[i] will be storing the number of solutions for value i.
            // n+1 rows are needed since the table is constructed in bottom up manner using the base case (n = 0)
            uint[] table = new uint[n + 1];

            // Base case (If given value is 0)
            table[0] = 1u;

            // Pick all denominations one by one and update the table[] values after the index
            // greater than or equal to the value of the picked coin
            for (int i = 0; i < m; i++)
            {
                for (long j = integralDenominations[i]; j <= n; j++)
                {
                    table[j] += table[j - integralDenominations[i]];
                }
            }

            return(table[n]);
        }
Exemplo n.º 2
0
        internal OptimalChangeSolution(long toChange, Currency operationCurrency, ushort[] table, IntegralDenomination?[] usedDenominations)
        {
            _denominations = new QuantifiedDenomination[0];

            ushort possibleSolution = table.Last();

            if (possibleSolution != ushort.MaxValue)
            {
                // at most as many denominations as used
                List <Denomination>  denominations       = new List <Denomination>(usedDenominations.Length);
                IntegralDenomination defaultDenomination = IntegralDenomination.Default(operationCurrency);

                long denomination = toChange;
                while (denomination > 0)
                {
                    IntegralDenomination usedDenomination = usedDenominations[denomination]
                                                            .GetValueOrDefault(defaultDenomination);
                    denominations.Add(usedDenomination.Denomination);
                    denomination -= usedDenomination.IntegralAmount;
                }
                _denominations = QuantifiedDenomination.Aggregate(denominations.OrderByDescending(d => d.Value))
                                 .ToArray();
            }
        }