A greenhouse volunteer wants a small tool that says which plants need water today. Each plant has its own interval: a fern every 3 days, a cactus every 10. Model it as a class that owns its state, validates every call, and never ends up half-updated.
Implement class Greenhouse:
Greenhouse()starts empty. Days are integers (day numbers, not dates).add_plant(name, every, day): pot a new plant onday. Potting counts as a watering on that day.everyis how many days it can go between waterings.ValueErrorif a plant callednamealready exists, or ifeveryisn't a positive integer.
water(name, day): record thatnamewas watered onday.KeyErrorfor an unknown plant;ValueErrorifdayis earlier than that plant's last watering (the log only moves forward; the same day again is fine).
remove_plant(name):KeyErrorif unknown.due(day) -> list[str]: every plant whose next watering (last watering + every) is on or beforeday. Most overdue first (largestday - next watering), ties broken by name A→Z. Doesn't change anything.
A call that raises must leave the greenhouse exactly as it was.
g = Greenhouse()
g.add_plant("fern", 3, day=0)
g.add_plant("cactus", 10, day=0)
g.add_plant("basil", 1, day=2)
g.due(3) # ["basil", "fern"] both due exactly on day 3
g.water("fern", 4)
g.due(5) # ["basil"] fern is next due on day 7
g.due(12) # ["basil", "fern", "cactus"] overdue by 9, 5 and 2 days
g.water("fern", 1) # ValueError: earlier than day 4
g.add_plant("fern", 2, day=5) # ValueError: already exists
g.water("mint", 5) # KeyError
Show hint
Keep one dict from name to a small record (a dataclass with every and last). Do all the checks at the top of each method, before assigning anything; due is a filter plus sorted(..., key=lambda n: (-(overdue), n)).