[LeetCode] 由 “打印机任务队列" 所想

一、这是个基础问题

Ref: Python之队列模拟算法(打印机问题)【首先研究这个问题作为开始】

任务队列

定义一个任务队列,来管理任务,而无需关心队列的”任务类型"。

复制代码
# 自定义队列类
class Queue(object):
def __init__(self): #初始化空队列 self.items = [] def isEmpty(self): #是否为空 return self.items == [] def enqueue(self, item): #入队,索引为0,即队尾在左侧 self.items.insert(0,item) def dequeue(self): #出队,列表最后一个,即队首在右侧 return self.items.pop() def size(self): #查看队列的大小 return len(self.items)
复制代码

  

遍历循环队列

index不变,elem变化

queue.enqueue(queue.dequeue)

 

index变化,elem不变

position = index % Queue.size()

 

 

打印机类

三个状态:(1)接到一个新任务,就一个key: task timeRemaining(2)忙么?(3)执行任务一秒钟,更新任务状态。

所以,打印机类的”执行任务“,外层是一个”秒针滴答”的循环

复制代码
# 打印机类 需要实时监测是否正在执行打印任务
class Printer(object):
def __init__(self, ppm): self.pagerate = ppm # 页面打印速率:打印一张需要多少秒 self.currentTask = None # 初始化当前任务 self.timeRemaining = 0 # 初始化剩余时间 # 计算正在执行的打印任务的剩余时长,即减去当前秒(1秒时长)后的时长 def tick(self): if self.currentTask != None: # 正在执行打印任务 self.timeRemaining = self.timeRemaining - 1 # 去除当前秒的任务剩余时长 if self.timeRemaining <= 0: # 当前打印任务结束后 self.currentTask = None # 在一次任务结束后将打印机设为空闲 # 对外接口:打印机是否忙碌 def busy(self): if self.currentTask != None: # 当前打印机有任务,则 return True # 忙碌 else: # 当前打印机无任务,则 return False # 空闲 # 进入下一个打印任务 def startNext(self, newtask): self.currentTask = newtask self.timeRemaining = newtask.getPages() * 60/self.pagerate # 新任务需要的时间秒数: (有几张 * 一张需要多少秒)
复制代码

 

任务类

创建一个 “随机大小“ 的任务;并设定好 “生日”

类中的只读属性,可以考虑使用@property。

复制代码
# 一个单独的打印任务
class Task(object):
def __init__(self,time): self.timestamp = time # 出生时间:任务被创建和被放入打印队列时的时间节点 self.pages = random.randrange(1,21) # 随机大小:随机生成1-20页的单个任务的打印页数 # 对外接口:获取时间节点,此处没用到。 def getStamp(self): return self.timestamp # 对外接口:获取页数 def getPages(self): return self.pages # 已经等待了多久;用于检索任务开始打印前在队列中的等待时长 def waitTime(self, currenttime): return currenttime - self.timestamp
复制代码

  

开始模拟

例如:评估下”一小时内“ 使用一台 “每分钟打印五张” 打印机的情况,进行模拟。

每一秒,要考虑两个事情:(1)有新任务?(2)能处理新任务?(3)打印机处理一次。

复制代码
# 指定时长、指定打印速率下的打印函数
def simulation(numSeconds, pagesPerMinute):
labprinter
= Printer(pagesPerMinute) # 实例化打印机类,参数为页/分钟 printQueue = Queue() # 创建打印队列 waitingtimes = [] # 初始化等待时长列表

# 模拟:时间是 一秒一秒 地流逝,每一秒都要考虑两个事情。 for currentSecond in range(numSeconds): #在指定时长numSeconds内的当前秒时 # (a) 有新来的打印任务嚒?
if newPrintTask(): #若有打印任务,则 task = Task(currentSecond) #创建打印任务,并记录当前时间节点 printQueue.enqueue(task) #将该打印任务入队
# (b) 若打印机不忙碌,且打印队列不为空,则 if (not labprinter.busy()) and (not printQueue.isEmpty()): nexttask = printQueue.dequeue() #出队 waitingtimes.append(nexttask.waitTime(currentSecond)) #将该任务等待时长加入等待列表 labprinter.startNext(nexttask) #打印该任务

# (c) 打印机执行一次 labprinter.tick() #计算正在执行的打印任务的剩余时长,并在一次任务结束后将打印机设为空闲

averageWait = sum(waitingtimes) / len(waitingtimes) #平均等待时长 print("Average Wait %6.2f secs %3d tasks remaining." % (averageWait, printQueue.size()))
复制代码

 

随机任务

条件判断之模拟,1/180的概率去做一件事。

# 使用随机函数创建打印任务
def newPrintTask():
    num = random.randrange(1, 181)              #生成随机数,平均3分钟有一个任务
    if num == 180:                              
        return True                             #有打印任务
    else:
        return False                            #没有打印任务

  

程序测试

if __name__ == '__main__':
    for i in range(10):                         #获取10次打印情况
        simulation(3600, 5)                     #获取1小时内,每分钟打印5张的打印情况

Output: 

复制代码
Average Wait  58.35 secs   0 tasks remaining.
Average Wait  85.43 secs   0 tasks remaining.
Average Wait  83.68 secs   4 tasks remaining.
Average Wait 107.12 secs   0 tasks remaining.
Average Wait  71.05 secs   0 tasks remaining.
Average Wait  30.77 secs   3 tasks remaining.
Average Wait 143.09 secs   0 tasks remaining.
Average Wait 195.75 secs   4 tasks remaining.
Average Wait 265.95 secs   1 tasks remaining.
Average Wait  70.94 secs   0 tasks remaining.
复制代码

 

  

二、基础总结

首先,这是一个 “模拟现实” 并做出评估的问题,思维模式具有一定的实际意义。

Input 端的两个随机特性;

    • 随机输入
    • 随机负载

代码样例如下:

for currentSecond in range(numSeconds): 
  if random.randrange(0, 180) == 180    # 随机输入
    task = Task(currentSecond)      # 随机负载
    printQueue.enqueue(task) 

  

class Task(object):

    def __init__(self,time):
        self.timestamp = time
        self.pages = random.randrange(1,21)     # 随机负载

 

End.

posted @   郝壹贰叁  阅读(547)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示