This is about as clear a solution as you'll ever find - three classes (PrintJob, JobQueue, and Printer) and a main() function to do the simulation:
class PrintJob:
def __init__(self, name, pages):
self.name = name
self.pages = pages
self.remaining = pages
def tick(self):
if self.remaining:
self.remaining -= 1
print("Job {}: {} / {} pages remain".format(self.name, self.remaining, self.pages))
def is_done(self):
return self.remaining == 0
class JobQueue:
def __init__(self):
self.jobs = []
def enqueue(self, job):
self.jobs.append(job)
def dequeue(self):
return self.jobs.pop(0)
def is_empty(self):
return not self.jobs
class Printer:
def __init__(self, name, job_queue):
self.name = name
self.job_queue = job_queue
self.current_job = None
def tick(self):
# make sure we have a job to work on
if self.current_job is None:
if self.job_queue.is_empty():
print("Printer {} is idle".format(self.name))
return
else:
self.current_job = self.job_queue.dequeue()
print("Printer {} got job {}".format(self.name, self.current_job.name))
# print!
print("Printer {} is printing...".format(self.name))
self.current_job.tick()
# see if job is finished
if self.current_job.is_done():
print("Printer {} finished job {}".format(self.name, self.current_job.name))
self.current_job = None
def is_idle(self):
return self.current_job is None
def main():
# create job queue and two printers
jobs = JobQueue()
p1 = Printer(1, jobs)
p2 = Printer(2, jobs)
# add jobs
jobs.enqueue(PrintJob(1, 5))
jobs.enqueue(PrintJob(2, 7))
jobs.enqueue(PrintJob(3, 13))
# cycle until queue is empty
tick = 0
while not (jobs.is_empty() and p1.is_idle() and p2.is_idle()):
tick += 1
print("\n=== Tick {} ===".format(tick))
p1.tick()
p2.tick()
print("\nAll done! Time for a pint...")
if __name__ == "__main__":
main()
and the final result looks like
=== Tick 1 ===
Printer 1 got job 1
Printer 1 is printing...
Job 1: 4 / 5 pages remain
Printer 2 got job 2
Printer 2 is printing...
Job 2: 6 / 7 pages remain
=== Tick 2 ===
Printer 1 is printing...
Job 1: 3 / 5 pages remain
Printer 2 is printing...
Job 2: 5 / 7 pages remain
=== Tick 3 ===
Printer 1 is printing...
Job 1: 2 / 5 pages remain
Printer 2 is printing...
Job 2: 4 / 7 pages remain
=== Tick 4 ===
Printer 1 is printing...
Job 1: 1 / 5 pages remain
Printer 2 is printing...
Job 2: 3 / 7 pages remain
=== Tick 5 ===
Printer 1 is printing...
Job 1: 0 / 5 pages remain
Printer 1 finished job 1
Printer 2 is printing...
Job 2: 2 / 7 pages remain
=== Tick 6 ===
Printer 1 got job 3
Printer 1 is printing...
Job 3: 12 / 13 pages remain
Printer 2 is printing...
Job 2: 1 / 7 pages remain
=== Tick 7 ===
Printer 1 is printing...
Job 3: 11 / 13 pages remain
Printer 2 is printing...
Job 2: 0 / 7 pages remain
Printer 2 finished job 2
=== Tick 8 ===
Printer 1 is printing...
Job 3: 10 / 13 pages remain
Printer 2 is idle
=== Tick 9 ===
Printer 1 is printing...
Job 3: 9 / 13 pages remain
Printer 2 is idle
=== Tick 10 ===
Printer 1 is printing...
Job 3: 8 / 13 pages remain
Printer 2 is idle
=== Tick 11 ===
Printer 1 is printing...
Job 3: 7 / 13 pages remain
Printer 2 is idle
=== Tick 12 ===
Printer 1 is printing...
Job 3: 6 / 13 pages remain
Printer 2 is idle
=== Tick 13 ===
Printer 1 is printing...
Job 3: 5 / 13 pages remain
Printer 2 is idle
=== Tick 14 ===
Printer 1 is printing...
Job 3: 4 / 13 pages remain
Printer 2 is idle
=== Tick 15 ===
Printer 1 is printing...
Job 3: 3 / 13 pages remain
Printer 2 is idle
=== Tick 16 ===
Printer 1 is printing...
Job 3: 2 / 13 pages remain
Printer 2 is idle
=== Tick 17 ===
Printer 1 is printing...
Job 3: 1 / 13 pages remain
Printer 2 is idle
=== Tick 18 ===
Printer 1 is printing...
Job 3: 0 / 13 pages remain
Printer 1 finished job 3
Printer 2 is idle
All done! Time for a pint...