An inventory with its own errors

Build the inventory again, with proper errors and a stock report.

What to build

A class with a custom exception and two kinds of report.

Requirements

  • add ITEM K adds stock. It prints nothing.
  • remove ITEM K prints removed, or out of stock: need X more using a custom OutOfStock exception.
  • report prints each item with stock as ITEM K, in alphabetical order, or empty.
  • low M prints the names of items with fewer than M left, alphabetically on one line, or none.

Input

The first line has n. Each of the next n lines is a command.

Output

Only what the commands above print.

Constraints

n is from 1 to 1000. All numbers are from 1 to 1000000. Items at zero remain known, but they are not in the report.

Example

Input:

5
add pen 10
add ink 2
remove pen 3
report
low 5

Output:

removed
ink 2
pen 7
ink

Why it works

Raising a specific error lets the method report a problem without printing anything, so the class stays reusable and the main loop decides what to show.

Examples

Example 1 · Input
5
add pen 10
add ink 2
remove pen 3
report
low 5
Expected output
removed
ink 2
pen 7
ink
Example 2 · Input
2
remove pen 1
report
Expected output
out of stock: need 1 more
empty

Prompts inside input() are ignored when checking, so input("n: ") is fine.

Hints

Hint 1

Define OutOfStock so that it inherits from Exception.

Hint 2

remove raises it with the shortfall, and the main loop catches it.

Hint 3

report sorts the items and skips those with zero left.

Solution

Show one correct solution (try it yourself first)
class OutOfStock(Exception):
    pass

class Inventory:
    def __init__(self):
        self.stock = {}

    def add(self, item, amount):
        self.stock[item] = self.stock.get(item, 0) + amount

    def remove(self, item, amount):
        have = self.stock.get(item, 0)
        if have < amount:
            raise OutOfStock(amount - have)
        self.stock[item] = have - amount

    def report(self):
        return [f"{item} {k}" for item, k in sorted(self.stock.items()) if k > 0]

    def low(self, minimum):
        return sorted(item for item, k in self.stock.items() if k < minimum)

shop = Inventory()
n = int(input())
for _ in range(n):
    parts = input().split()
    if parts[0] == "add":
        shop.add(parts[1], int(parts[2]))
    elif parts[0] == "remove":
        try:
            shop.remove(parts[1], int(parts[2]))
            print("removed")
        except OutOfStock as error:
            print(f"out of stock: need {error} more")
    elif parts[0] == "report":
        lines = shop.report()
        print("\n".join(lines) if lines else "empty")
    else:
        names = shop.low(int(parts[1]))
        print(" ".join(names) if names else "none")

Lesson: Project: a shop inventory →