Crafting Bench
MediumOnline Assessment
Fill a queue of orders at a workshop that uses what is on the shelf first and otherwise builds parts from recipes, trying recipes in a fixed order.
The workshop has a stock of items and a list of recipes. recipes[r] = [item, yield, ingredients] means: one run of recipe r produces yield units of item and uses ingredients, a list of [ingredient, count] pairs. An item may have several recipes; they are tried in the order they appear in recipes. An item with no recipe (a raw material) can only come from stock. Recipes never form a cycle.
To obtain one unit of item X:
- If the stock holds at least one X, take it (stock goes down by 1). Done.
- Otherwise try X's recipes in list order. To try a recipe, obtain its ingredients one pair at a time in the listed order: for
[ing, k], obtain one unit ofing(by this same procedure)ktimes. If every ingredient is obtained, the recipe succeeds: the ingredients are consumed, and theyieldunits of X are made, one of which is the unit being obtained and the otheryield - 1go into stock. Done. - If a recipe fails part-way, everything it consumed or made while trying is put back exactly as it was before the attempt, and the next recipe is tried.
- If no recipe succeeds (or X has none), X cannot be obtained and the stock is unchanged.
An order [item, qty] is filled by obtaining qty units of item, one after another. If all succeed, the order is "OK" and the units leave the workshop (they are not returned to stock). If any unit cannot be obtained, the order is "SHORT" and the stock is restored to exactly what it was before this order. Orders are processed in sequence on the same stock.
Input: recipes, stock (a list of [item, count]), and orders (a list of [item, qty]).
Output: a list [results, leftover]: results has "OK" or "SHORT" for each order, and leftover lists the final stock as [item, count] pairs for items with count above 0, sorted by item name.
Example 1
- Input:
- [[["plank",4,[["log",1]]],["stick",4,[["plank",2]]],["pickaxe",1,[["stick",2],["ingot",3]]],["pickaxe",1,[["stick",2],["gem",2]]]],[["log",1],["ingot",2],["gem",5]],[["pickaxe",1],["pickaxe",1],["pickaxe",2],["stick",2]]]
- Output:
- [["OK","OK","SHORT","OK"],[["gem",1],["ingot",2],["stick",2]]]
- Explanation
- One log becomes 4 planks (3 stay in stock), 2 planks become 4 sticks, and so on. The first pickaxe tries recipe 1: it builds the sticks, takes the 2 ingots in stock, and then cannot find a third ingot, so everything that attempt used is put back and recipe 2 runs: sticks again, plus 2 gems. The second pickaxe finds the 2 sticks the first one left in stock; recipe 1 fails on the ingots again, recipe 2 spends 2 more gems (1 left). The order for 2 pickaxes would need 4 gems in total (1 left), so it is
SHORTand the stock is exactly what it was. The last order for 2 sticks takes them from stock.
Example 2
- Input:
- [[["bolt",2,[["rod",1]]],["frame",1,[["bolt",3],["plate",1]]],["plate",1,[["ore",2],["coal",1]]],["plate",2,[["ore",1]]]],[["rod",2],["ore",3],["coal",0],["bolt",1]],[["frame",1],["frame",1],["plate",3]]]
- Output:
- [["OK","SHORT","OK"],[["ore",1],["rod",1]]]
- Explanation
- Order 1 needs 3 bolts and a plate. The bolt in stock is used first, then one run of the bolt recipe turns 1 rod into 2 bolts (one left over for the third bolt). For the plate, recipe 1 consumes 2 ore and then fails on the missing coal, so it is undone; recipe 2 makes 2 plates from 1 ore and 1 plate stays in stock. Order 2 needs 3 bolts but only 1 rod is left (2 bolts), so it is
SHORTand nothing changes. Order 3 asks for 3 plates: the plate in stock, then one run of recipe 2 (the second plate, with a third left over).
Example 3
- Input:
- [[["cog",1,[["tin",1]]],["cog",3,[["iron",1]]],["clock",1,[["cog",4]]]],[["tin",2],["iron",1],["cog",1]],[["clock",1],["cog",1],["gear",1],["clock",2]]]
- Output:
- [["OK","OK","SHORT","SHORT"],[["cog",1]]]
- Explanation
- A clock needs 4 cogs. One cog is in stock, two more come from the tin recipe (the first listed), and for the fourth cog tin has run out, so the second recipe turns the iron into 3 cogs (one is used, 2 stay in stock). The next order for 1 cog takes one of them. The order for a gear is
SHORT: it has no recipe and is not in stock. The final order for 2 clocks takes the one remaining cog, finds no way to make more, and isSHORT, so that cog is left in stock.
Constraints
- 0 ≤ recipes.length ≤ 12; item names are lowercase words; 1 ≤ yield ≤ 5; each recipe has 1 to 4 ingredient pairs with 1 ≤ count ≤ 4; recipes never form a cycle
- 0 ≤ stock.length ≤ 12, each item appears at most once, counts between 0 and 30
- 0 ≤ orders.length ≤ 20; 1 ≤ qty ≤ 6