SDE Path

Coffee Machine

Medium

Coffee Machine

Stock ingredients, define recipes, brew on demand — an inventory transaction that must be all-or-nothing.

Requirements

  • Inventory is a running count per ingredient; addIngredient accumulates rather than overwrites.
  • A recipe is an ordered list of (ingredient, quantity) requirements, built one addRecipe call at a time. Each beverage is fully defined before it is brewed, and each ingredient appears at most once per beverage.
  • makeBeverage is all-or-nothing: check the recipe in insertion order and, on the first ingredient whose stock is below the required quantity, return insufficient:<ingredient> and consume nothing. Only when every requirement is met does it decrement all of them and return served.
  • Availability is stock ≥ required (an exact match counts as available).
  • Everything is deterministic — no timers, no randomness.

API to implement

Implement the class CoffeeMachine. The I/O driver is already written in the starter code — it parses the command script below and calls your methods. You only implement the class.

| Command | Returns | Behavior | |---|---|---| | addIngredient <name> <qty> | — | Add qty units of ingredient name to the inventory. Accumulates across calls (adding water 20 then water 30 yields 50). | | addRecipe <beverage> <ingredient> <qty> | — | Append one requirement — qty units of ingredient — to beverage's recipe. Called once per ingredient, in the order the ingredients should be checked. | | makeBeverage <beverage> | string | Brew beverage. If every ingredient in its recipe has enough stock, consume them all and return served. Otherwise consume nothing and return insufficient:<ingredient>, naming the first short ingredient in recipe order. |

Input format

The first line contains Q, the number of operations. Each of the next Q lines is one command as listed above. String arguments contain no spaces.

Output format

For each command with a non-void return, print its result on its own line, in order. The driver does this for you — your methods just return values.

This is a design problem: the hidden tests exercise edge cases and interaction sequences, not performance tricks. Model the state cleanly and the tests will pass.

Sample cases

Example 1
Input
11
addIngredient water 100
addIngredient milk 10
addIngredient beans 100
addRecipe latte water 50
addRecipe latte milk 30
addRecipe latte beans 20
makeBeverage latte
addIngredient milk 50
makeBeverage latte
makeBeverage latte
makeBeverage latte
Expected output
insufficient:milk
served
served
insufficient:water
Example 2
Input
7
addIngredient beans 30
addRecipe espresso water 20
addRecipe espresso beans 18
makeBeverage espresso
addIngredient water 50
makeBeverage espresso
makeBeverage espresso
Expected output
insufficient:water
served
insufficient:beans