一、这是个基础问题

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] 由 “打印机任务队列" 所想的更多相关文章

  1. [LeetCode] 由 “找零钱" 所想

    Ref: [Optimization] Dynamic programming[寻找子问题] Ref: [Optimization] Advanced Dynamic programming[优于re ...

  2. [Code] 变态之人键合一

    目的也比较单纯,选一门语言,走向人键合一. 选了两本书作为操练场:<精通Python设计模式>.<Data Structure and Algorithm in Python> ...

  3. 装逼名词 bottom-half,软中断,preemptive选项

    bottom-half http://bbs.csdn.net/topics/60226240 在中断,异常和系统调用里看Linux中断服务一般都是在关闭中断的情况下执行的,以避免嵌套而是控制复杂化L ...

  4. WPF打印票据

    最近工作的内容是有关于WPF的,整体开发没有什么难度,主要是在打印上因为没有任何经验,犯了一些难,不过还好,解决起来也不是很费劲. WPF打印票据或者是打印普通纸张区别不大,只是说打印票据要把需要打的 ...

  5. 《转》高级Unix命令

    原文链接:http://coolshell.cn/articles/1044.html 在Unix操作中有太多太多的命令,这些命令的强大之处就是一个命令只干一件事,并把这件事干好.Do one thi ...

  6. 一些不太常用的Linux命令

    ACCTCOM 查看所有用户执行过的进程 acctcom | tail - 查看指定用户执行过的进程/命令 acctcom -u <username> | tail - 使用一个正则表达式 ...

  7. Python 实现队列

    操作 Queue() 创建一个空的队列 enqueue(item) 往队列中添加一个item元素 dequeue() 从队列头部删除一个元素 is_empty() 判断一个队列是否为空 size() ...

  8. 高级Unix命令

    在Unix操作中有太多太多的命令,这些命令的强大之处就是一个命令只干一件事,并把这件事干好.Do one thing, do it well.这是unix的哲学.而且Unix首创的管道可以把这些命令任 ...

  9. 数据结构之队列(Queue)

    1,队列的定义 队列:是一种先进先出的数据结构,如下图所示,现进去的数据在队列前面(front),先出队列,后进入队列的数据在后面(rear),后出队列. 队列常用操作: q=Queue() #创建队 ...

随机推荐

  1. Zabbix监控华为路由器配置

    zabbix监控华为路由器 一.配置路由器界面: 开启snmpv2c功能,同时勾选v2c版本(不要勾v1,不安全,其实v2也不安全,如果很注重安全的话,一定要只配置v3). 手里没有路由器登录账号,大 ...

  2. SpringBoot进阶教程(六十一)intellij idea project下建多个module搭建架构(下)

    在上一篇文章<SpringBoot进阶教程(六十)intellij idea project下建多个module(上)>中,我们已经介绍了在intellij idea中创建project之 ...

  3. vim文件时,误用了ctrl+z命令,该怎么办?

    linux中,当正在使用vim命令编辑文件,退出时,如果误使用了 ctrl+z ,当前目录中会多一个隐藏文件. 比如我正在编辑 t.txt 文件时,误以为我之前使用的是 tail 命令,直接使用 ct ...

  4. Nginx介绍与反向代理

    Nginx的产生 没有听过Nginx?那么一定听过它的"同行"Apache吧!Nginx同Apache一样都是一种WEB服务器.基于REST架构风格,以统一资源描述符(Unifor ...

  5. 【Leetcode】【简单】【17. 整数反转】【JavaScript】

    题目描述 7. 整数反转 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例 1: 输入: 123输出: 321 示例 2: 输入: -123输出: -321示例 3: 输 ...

  6. Spring Cloud开发人员如何解决服务冲突和实例乱窜?

    一.背景 在我们开发微服务架构系统时,虽然说每个微服务都是孤立的可以单独开发,但实际上并非如此,要调试和测试你的服务不仅需要您的微服务启动和运行,还需要它的上下文服务.依赖的基础服务等都要运行:但如果 ...

  7. [翻译] .NET Core 3.0 Preview 9 发布

    原文: Announcing .NET Core 3.0 Preview 9 今天,我们宣布推出 .NET Core 3.0 Preview 9.就像 Preview 8 一样,我们专注于打磨 .NE ...

  8. Python数据分析之Pandas读写外部数据文件

    1 引言 数据分析.数据挖掘.可视化是Python的众多强项之一,但无论是这几项中的哪一项都必须以数据作为基础,数据通常都存储在外部文件中,例如txt.csv.excel.数据库.本篇中,我们来捋一捋 ...

  9. BadBoy+JMeter来录制和运行Web测试脚本

    参考: http://jingyan.baidu.com/article/5d368d1ef548d43f61c05761.html http://www.51testing.com/html/00/ ...

  10. E-Explorer_2019牛客暑期多校训练营(第八场)

    题意 n个点,m条边,u,v,l,r表示点u到点v有一条边,且只有编号为\([l,r]\)的人能通过,问从点1到点n有哪些编号的人能通过 题解 先对\(l,r\)离散化,用第七场找中位数那题同样的形式 ...