Course content
Design a Vending Machine
Medium·Tagsllddesignvending-machinestateencapsulation
Problem Statement
Design a vending machine that holds an inventory of items, accepts coins, and dispenses items with the correct change. Prices and balances are in cents (integers — no floating-point money).
API contract
```java
class VendingMachine {
public VendingMachine(); // starts with no inventory and zero balance
/** Stock an item code with a unit price (cents) and an initial quantity. Calling stock
* on an existing code REPLACES the price and quantity for that code (lets the operator
* restock). Throws IllegalArgumentException for non-positive priceCents or negative
* quantity. */
public void stock(String code, int priceCents, int quantity);
/* Add money to the inserted balance. Throws IllegalArgumentException for cents <= 0. /
public void insertCoin(int cents);
/** Dispense the requested item.
* - Throws IllegalArgumentException if the code is unknown.
* - Throws IllegalStateException if the item is out of stock.
* - Throws IllegalStateException if the inserted balance is less than the price.
- On success: decrement inventory, return change (balance - price), reset balance to 0. /
public int dispense(String code);
/** Return all inserted money to the customer and reset balance to 0. Returns the amount
* refunded (0 if nothing was inserted). Always succeeds. */
public int refund();
public int getBalance();
public int getInventory(String code); // returns 0 for unknown codes
}
```
The validator runs three checks:
1. *dispense_basic_and_change* — stock `"A1"` at 150¢ × 2; insert 200¢; `dispense("A1")` returns 50¢ change, decrements inventory to 1, resets balance to 0. Insert 150¢, dispense again → returns 0¢ change, inventory now 0.
2. *error_states* — `dispense("GHOST")` throws `IllegalArgumentException` (unknown code). `dispense` with insufficient inserted balance throws `IllegalStateException`; the inserted balance and inventory are unchanged. `dispense` of a sold-out item throws `IllegalStateException`.
3. *refund_resets_balance* — insert 100¢ + 50¢, `refund()` returns 150¢, `getBalance()` is 0, the machine can accept new coins and dispense again.
The stub `VendingMachine` throws `UnsupportedOperationException` from every method, so it fails every check until you implement it.
Starter code and validators are available in Java, Python, and C++.
Examples
Example 1
Input
var v = new VendingMachine(); v.stock("A1", 150, 2); v.insertCoin(200); v.dispense("A1")Output
"50"Why
200¢ inserted, 150¢ price → 50¢ change. Inventory drops to 1 and balance resets to 0.
Example 2
Input
v.insertCoin(50); v.dispense("A1")Output
"throws IllegalStateException"Why
50¢ < 150¢ price. The dispense fails; the 50¢ stays in the machine for a second insertCoin or a refund.
Example 3
Input
v.insertCoin(100); v.refund(); v.getBalance()Output
"0"Why
Refund returns the inserted 100¢ to the customer and resets the inserted balance.
Constraints
- •All amounts are in cents (int).
- •stock(code, priceCents, quantity) throws IllegalArgumentException if priceCents <= 0 or quantity < 0. Re-stocking an existing code replaces both price and quantity.
- •insertCoin(cents) throws IllegalArgumentException if cents <= 0.
- •dispense throws IllegalArgumentException for unknown codes; IllegalStateException for out-of-stock or insufficient balance.
- •On a successful dispense, balance resets to 0 (the change is returned, not retained).
- •On a failed dispense, balance and inventory are unchanged.
- •refund always succeeds and returns the inserted balance (0 if nothing was inserted).
Hints
Stuck? Reveal a nudge toward the right pattern, one step at a time.
Hint 1
Use a small inner class (or record) to bundle price and quantity per item: `class ItemRecord { int priceCents; int quantity; }` — held in a Map<String, ItemRecord>.
Hint 2
Use IllegalArgumentException for caller bugs (bad input, unknown code) and IllegalStateException for machine-state issues (out of stock, insufficient balance). The validator distinguishes these.
Hint 3
On a failed dispense, do NOT consume the balance or decrement inventory. The natural way is: validate everything first, then mutate. Failing midway through is the bug everyone makes once.
Hint 4
Successful dispense: return (balance - price) and reset balance to 0. The customer received their change; the machine has no money owed.
Hint 5
refund() is a guaranteed-success operation: read the balance, set balance = 0, return the saved value. It can be called when balance is already 0 (returns 0).