Use only in-memory state. Names and worker identifiers are strings; priorities are arbitrary integers. Integer timestamps, durations, and capacities exclude booleans. There is no execution, sleeping, wall clock, threading, disk, or network.

Prototype: implement PriorityQueue(). add(name, priority) -> int creates a task with the next integer identifier starting at 1. Duplicate names are valid. pop() -> tuple[int, str] | None removes the highest-priority task, breaking ties by smaller identifier, and returns (id, name) or None when empty. Removed identifiers are never reused. Queues are independent.

Final: implement TaskScheduler():

  • add_task(name, priority) -> int: create a pending task with an increasing integer identifier starting at 1. Duplicate names and negative priorities are valid. Identifiers are never reused.
  • add_worker(worker_id, capacity) -> bool: require a positive integer capacity, otherwise raise ValueError first. Register a worker and return True; duplicates return False without changing their original capacity.
  • dispatch(ts, worker_id, lease) -> dict | None: require positive integer lease, otherwise raise ValueError before advancing time. After expiring old leases, return None if the worker is unknown, full, or no task is pending. Otherwise choose highest priority then smallest identifier, assign it on [ts, ts + lease), and return its snapshot. Each successful dispatch receives the next globally increasing integer lease token starting at 1; failures do not consume tokens.
  • complete(ts, task_id, token) -> bool: after expiry, return True only for a currently running task with exactly that token. Make it permanently done and clear assignment metadata. Wrong tokens, unknown tasks, completed tasks, and expired leases return False without a requested state change.
  • get_task(ts, task_id) -> dict | None: after expiry, return its snapshot or None if unknown.
  • active(ts, worker_id) -> list[dict]: after expiry, return snapshots of that worker's running tasks ordered by numeric task identifier. An unknown worker returns [].

Every task snapshot has exactly these keys: id, name, priority, status, worker, expires_at, token. Status is pending, running, or done. Assignment fields are None for pending/done tasks. Every returned list and dictionary is a fresh snapshot.

Only the four methods taking ts advance time. Their valid calls, including calls returning None or False, accept nonnegative nondecreasing timestamps; equal times are allowed. A negative or regressing timestamp raises ValueError before any state or time change. All valid timed calls first expire leases with expires_at <= ts; expired tasks become pending and receive a new token if reassigned. Rejected requests otherwise preserve state. Instances share no tasks, workers, tokens, or clocks. Run python main.py --stage prototype, then python main.py --stage final (the default). Edit exercise.py; leave main.py unchanged.

Drag or use the arrow keys to resize. Home collapses the question; End collapses the editor. Enter or double-click resets the split.
Loading editor…
No results yet.

Complete the starter code, then run the checks.
Results and errors will appear here.