CashDispenser.java
package com.algorithms.greedy.coinchange.applied;
import com.algorithms.greedy.coinchange.classic.CoinChange;
import java.util.Arrays;
/**
* A legacy bank's self-service withdrawal kiosk, deciding how many of each banknote/coin to
* dispense for a withdrawal. Real currency denomination sets — Brazilian real notes and coins
* included — are canonical: greedy (always dispense the largest denomination that still fits)
* gives the true minimum note/coin count, which is exactly what a kiosk with limited cassette
* capacity wants. Amounts are handled in centavos ({@code long}) to avoid floating-point error
* on money.
*/
public final class CashDispenser {
/** BRL notes and coins, in centavos: R$200 down to R$0.01. Canonical — greedy is optimal here. */
public static final int[] BRL_CENTAVOS_DENOMINATIONS = {
20000, 10000, 5000, 2000, 1000, 500, 200, 100, 50, 25, 10, 5, 1,
};
public int dispenseNoteCount(long withdrawalAmountCentavos) {
if (withdrawalAmountCentavos < 0) {
throw new IllegalArgumentException("withdrawalAmountCentavos must be >= 0");
}
if (withdrawalAmountCentavos > Integer.MAX_VALUE) {
throw new IllegalArgumentException("withdrawalAmountCentavos exceeds this kiosk's per-transaction limit");
}
int[] denominations = Arrays.copyOf(BRL_CENTAVOS_DENOMINATIONS, BRL_CENTAVOS_DENOMINATIONS.length);
return CoinChange.greedyCoinCount(denominations, (int) withdrawalAmountCentavos);
}
}