// NOTE: Trully random calculation would involve picking a random combination of change from every single
        // possible combination of denominations for the given change amount.
        // (https://andrew.neitsch.ca/publications/m496pres1.nb.pdf)
        //
        // I would give my client this option in reality, but explain that this would require some extensive
        // research on my part. Rather than taking the time to implement that solution, I used the algorithm
        // of choosing a denomination at random and subracting a random amount of the denomination it from
        // the change, until I account for all the change.
        public Dictionary <CashDenominations, int> CalculateRandomAmountsOfChange(CashTransaction cashTransaction)
        {
            Dictionary <CashDenominations, int> result = new Dictionary <CashDenominations, int>();
            int remainderOfChange = cashTransaction.ChangeTotal;
            List <CashDenominations> cashDenominations =
                Enum.GetValues(typeof(CashDenominations))
                .Cast <CashDenominations>()
                .ToList();

            while (remainderOfChange > 0)
            {
                int randomDenominationIndex = Random.Next(cashDenominations.Count);

                CashDenominations randomDenomination = cashDenominations[randomDenominationIndex];
                int randomDenominationAsInt          = (int)randomDenomination;
                if (randomDenominationAsInt <= remainderOfChange)
                {
                    int randomAmoutOfTheDenomination =
                        Random.Next(1, remainderOfChange / randomDenominationAsInt + 1);
                    remainderOfChange -= randomDenominationAsInt * randomAmoutOfTheDenomination;
                    // See if denom has entry, if not, add + make value 1
                    // If so, increment the value.
                    if (result.ContainsKey(randomDenomination))
                    {
                        result[randomDenomination] += randomAmoutOfTheDenomination;
                    }
                    else
                    {
                        result.Add(randomDenomination, randomAmoutOfTheDenomination);
                    }
                }
            }
            return(result);
        }
        // Minimum and random calculations are in separate functions for readability and
        // testing.
        public Dictionary <CashDenominations, int> CalculateMinimumAmountsOfChange(CashTransaction cashTransaction)
        {
            Dictionary <CashDenominations, int> result = new Dictionary <CashDenominations, int>();
            int remainderOfChange = cashTransaction.ChangeTotal;

            CashDenominations[] cashDenominationsSortedFromGreatestToLeast =
                Enum.GetValues(typeof(CashDenominations))
                .Cast <CashDenominations>()
                .Reverse <CashDenominations>()
                .ToArray <CashDenominations>();
            foreach (CashDenominations cashDenomination in cashDenominationsSortedFromGreatestToLeast)
            {
                int cashDenominationAsInt = (int)cashDenomination;
                int denominationCount     = remainderOfChange / cashDenominationAsInt;
                result.Add(cashDenomination, denominationCount);
                if (remainderOfChange > cashDenominationAsInt)
                {
                    remainderOfChange %= cashDenominationAsInt;
                }
            }
            return(result);
        }