At an airport, handlers put bags on a carousel and passengers wait for their own bag. Every bag has a tag (a string); several bags may share a tag (a family checked in three suitcases).
Implement Carousel() with:
unload(tag) -> None: a handler puts one bag with this tag on the belt.claim(tag, timeout=None) -> bool: a passenger waits until a bag with this tag is on the belt, takes it off (one bag) and returnsTrue. With atimeoutin seconds, give up after that long and returnFalse; withNone, wait as long as it takes.on_belt() -> int: how many bags are on the belt right now.
Many passengers wait at once, each for a different (or the same) tag.
c = Carousel()
# passenger A: c.claim("AMS-17") -> waits
# passenger B: c.claim("LIS-02") -> waits
c.unload("LIS-02") # B returns True, A keeps waiting
c.unload("AMS-17") # A returns True
c.claim("NRT-99", timeout=0.1) # False after ~0.1s
c.unload("X"); c.unload("X"); c.on_belt() # 2
A bag must go to one passenger only: two passengers waiting for the same tag and one bag means one gets True and the other keeps waiting.
Constraints: don't sleep or busy-wait.
Show hint
Keep a Counter of tags on the belt behind one threading.Condition. claim does cond.wait_for(lambda: bags[tag] > 0, timeout) and only takes the bag if that returned True; unload must call notify_all(), not notify(): a single notify() may wake a passenger waiting for a different tag, who goes back to sleep, and the right one is never woken.