[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.
[LeetCode] 由 “打印机任务队列" 所想的更多相关文章
- [LeetCode] 由 “找零钱" 所想
Ref: [Optimization] Dynamic programming[寻找子问题] Ref: [Optimization] Advanced Dynamic programming[优于re ...
- [Code] 变态之人键合一
目的也比较单纯,选一门语言,走向人键合一. 选了两本书作为操练场:<精通Python设计模式>.<Data Structure and Algorithm in Python> ...
- 装逼名词 bottom-half,软中断,preemptive选项
bottom-half http://bbs.csdn.net/topics/60226240 在中断,异常和系统调用里看Linux中断服务一般都是在关闭中断的情况下执行的,以避免嵌套而是控制复杂化L ...
- WPF打印票据
最近工作的内容是有关于WPF的,整体开发没有什么难度,主要是在打印上因为没有任何经验,犯了一些难,不过还好,解决起来也不是很费劲. WPF打印票据或者是打印普通纸张区别不大,只是说打印票据要把需要打的 ...
- 《转》高级Unix命令
原文链接:http://coolshell.cn/articles/1044.html 在Unix操作中有太多太多的命令,这些命令的强大之处就是一个命令只干一件事,并把这件事干好.Do one thi ...
- 一些不太常用的Linux命令
ACCTCOM 查看所有用户执行过的进程 acctcom | tail - 查看指定用户执行过的进程/命令 acctcom -u <username> | tail - 使用一个正则表达式 ...
- Python 实现队列
操作 Queue() 创建一个空的队列 enqueue(item) 往队列中添加一个item元素 dequeue() 从队列头部删除一个元素 is_empty() 判断一个队列是否为空 size() ...
- 高级Unix命令
在Unix操作中有太多太多的命令,这些命令的强大之处就是一个命令只干一件事,并把这件事干好.Do one thing, do it well.这是unix的哲学.而且Unix首创的管道可以把这些命令任 ...
- 数据结构之队列(Queue)
1,队列的定义 队列:是一种先进先出的数据结构,如下图所示,现进去的数据在队列前面(front),先出队列,后进入队列的数据在后面(rear),后出队列. 队列常用操作: q=Queue() #创建队 ...
随机推荐
- python 编码报错问题 'ascii' codec can't encode characters 解决方法
python在安装时,默认的编码是ascii, 当程序中出现非ascii编码时,python的处理常常会报这样的错 'ascii' codec can't encode characters pyth ...
- iOS 11 变化
首先我是开发者,更关心对技术的影响,我又需要关注.学习哪些技术,猫神的文章:http://www.cocoachina.com/ios/20170607/19457.html 介绍了 ******** ...
- copy好文“IT34岁危机破解心法”
在博客园中偶然发现一个好文,收藏并记录以下.在工作中更多的从企业单位用人角度去思考,或许能在职场及职业规划中更加的游刃有余,有的放矢.下面是原文. 本文题目虽是“IT人34岁危机”破解心法,但内容同样 ...
- vue项目中引入Sass
Sass作为目前成熟,稳定,强大的css扩展语言,让越来越多的前端工程师喜欢上它.下面介绍了如何在vue项目 中引入Sass. 首先在项目文件夹执行命令 npm install vue-cli -g, ...
- HandlerMethodArgumentResolver(三):基于消息转换器的参数处理器【享学Spring MVC】
每篇一句 一个事实是:对于大多数技术,了解只需要一天,简单搞起来只需要一周.入门可能只需要一个月 前言 通过 前面两篇文章 的介绍,相信你对HandlerMethodArgumentResolver了 ...
- HDU 6053(莫比乌斯反演)
题意略. 思路:首先想到暴力去扫,这样的复杂度是n * min(ai),对于gcd = p,对答案的贡献应该是 (a1 / p) * (a2 / p) * .... * (an / p),得出这个贡献 ...
- 【数据库】MySQL 函数大全包含示例(涵盖了常用如时间、数字、字符串处理、数据流函数的和一些冷门的)
ps:博客园markdown不能自动生成列表,更好的阅读体验可访问我的个人博客http://www.isspark.com/archives/mysqlFunctionDesc 数学函数(Mathem ...
- effective java 3th item1:考虑静态工厂方法代替构造器
传统的方式获取一个类的实例,是通过提供一个 public 构造器.这里有技巧,每一个程序员应该记住.一个类可以对外提供一个 public 的 静态工厂方法 ,该方法只是一个朴素的静态方法,不需要有太多 ...
- java生成动态验证码
import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.Graphics2D;impor ...
- JAVA实现读取图片
话不读说 直接上代码 package cn.kgc.ssm.common; import java.io.*; /** * @author * @create 2019-08-15 9:36 **/ ...