Python利用带权重随机数解决抽奖和游戏爆装备问题


Posted in Python onJune 16, 2016

关于带权随机数
为了帮助理解,先来看三类随机问题的对比:
1.已有n条记录,从中选取m条记录,选取出来的记录前后顺序不管。
实现思路:按行遍历所有记录,约隔n/m条取一个数据即可
2.在1类情况下,还要求选取出来的m条记录是随机排序的
实现思路: 给n条记录,分别增加一列标记,值为随机选取的1至n之间的不重复数据。
3.区别于1,2类问题, 如果记录是有权重的,如何结合权重去随机选取。 比如A的权重为10, B的权重股为5, C的权重为1, 则随机选取4个时可能应该出现AABB。
第3类问题便是本文重点了。
实现思路: 以 A:10, B:5, C:1 三条记录上随机选取4条为例,(是否以权重排序这个无所谓)
    对于
    A 10
    B 5
    C 1
首先,将第n行的数值赋为第n行加第n-1行的,递归执行,如下:
    A 10
    B 15
    C 16
然后每次从[1,16]随机选取一个数,如果落在[1,10]之间,则选取A,如果落在(10,15]之间则选B,如果落在(16,16]之间则选取C, 图示如下,谁占的区间大(权重高),被选上的概率更大。

Python利用带权重随机数解决抽奖和游戏爆装备问题

在抽奖和游戏爆装备中的运用
带权随机在游戏开发中重度使用,各种抽奖和爆装备等.
运营根据需要来配置各个物品出现的概率.
今天要说的这个带权随机算法思想很简单,就是"把所有物品根据其权重构成一个个区间,权重大的区间大.可以想象成一个饼图.  然后,扔骰子,看落在哪个区间,"
举个栗子,有个年终抽奖,物品是iphone/ipad/itouch.
主办方配置的权重是[('iphone', 10), ('ipad', 40), ('itouch', 50)].
用一行代码即可说明其思想,即random.choice(['iphone']*10 + ['ipad']*40 + ['itouch']*50).
下面,我们写成一个通用函数.

#coding=utf-8 
import random 
def weighted_random(items): 
  total = sum(w for _,w in items) 
  n = random.uniform(0, total)#在饼图扔骰子 
  for x, w in items:#遍历找出骰子所在的区间 
    if n<w: 
      break 
    n -= w 
  return x 
 
print weighted_random([('iphone', 10), ('ipad', 40), ('itouch', 50)])

上面的代码够直观,不过细心的会发现,每次都会计算total,每次都会线性遍历区间进行减操作.其实我们可以先存起来,查表就行了.利用accumulate+bisect二分查找.
物品越多,二分查找提升的性能越明显.

#coding=utf-8 
class WeightRandom: 
  def __init__(self, items): 
    weights = [w for _,w in items] 
    self.goods = [x for x,_ in items] 
    self.total = sum(weights) 
    self.acc = list(self.accumulate(weights)) 
 
  def accumulate(self, weights):#累和.如accumulate([10,40,50])->[10,50,100] 
    cur = 0 
    for w in weights: 
      cur = cur+w 
      yield cur 
 
  def __call__(self): 
    return self.goods[bisect.bisect_right(self.acc , random.uniform(0, self.total))] 
 
wr = WeightRandom([('iphone', 10), ('ipad', 40), ('itouch', 50)]) 
print wr()
Python 相关文章推荐
Python ORM框架SQLAlchemy学习笔记之安装和简单查询实例
Jun 10 Python
实例讲解Python设计模式编程之工厂方法模式的使用
Mar 02 Python
win10系统中安装scrapy-1.1
Jul 03 Python
简单谈谈python中的多进程
Nov 06 Python
对python中执行DOS命令的3种方法总结
May 12 Python
python将秒数转化为时间格式的实例
Sep 16 Python
PyQt5 对图片进行缩放的实例
Jun 18 Python
python实现列表的排序方法分享
Jul 01 Python
如何使用Python脚本实现文件拷贝
Nov 20 Python
python 写一个性能测试工具(一)
Oct 24 Python
Python使用tkinter实现小时钟效果
Feb 22 Python
Python中time与datetime模块使用方法详解
Mar 31 Python
Python黑魔法@property装饰器的使用技巧解析
Jun 16 #Python
Python实现类似jQuery使用中的链式调用的示例
Jun 16 #Python
浅析Python中else语句块的使用技巧
Jun 16 #Python
python基础教程之分支、循环简单用法
Jun 16 #Python
python3音乐播放器简单实现代码
Apr 20 #Python
使用python3.5仿微软记事本notepad
Jun 15 #Python
python3.5仿微软计算器程序
Mar 30 #Python
You might like
syphon 虹吸式咖啡冲泡冲煮倒水的得与失
2021/03/03 冲泡冲煮
改变Apache端口等配置修改方法
2008/06/05 PHP
php 操作调试的方法
2012/07/12 PHP
PHP关联数组的10个操作技巧
2013/01/21 PHP
Windows上php5.6操作mongodb数据库示例【配置、连接、获取实例】
2019/02/13 PHP
Javascript Global对象
2009/08/13 Javascript
node.js中的http.response.writeHead方法使用说明
2014/12/14 Javascript
jQuery里filter()函数与find()函数用法分析
2015/06/24 Javascript
JQuery实现级联下拉框效果实例讲解
2015/09/17 Javascript
js实现(全选)多选按钮的方法【附实例】
2016/03/30 Javascript
微信小程序 实现列表项滑动显示删除按钮的功能
2017/04/13 Javascript
JavaScript箭头(arrow)函数详解
2017/06/04 Javascript
JavaScript选取(picking)和反选(rejecting)对象的属性方法
2017/08/16 Javascript
jQuery滑动效果实现方法分析
2018/09/05 jQuery
ndm:NPM的桌面GUI应用程序
2018/10/15 Javascript
浅谈bootstrap layer.open中end的使用方法
2019/09/12 Javascript
[01:33:14]LGD vs VP Supermajor 败者组决赛 BO3 第二场 6.10
2018/07/04 DOTA
win7安装python生成随机数代码分享
2013/12/27 Python
Python urlopen()函数 示例分享
2014/06/12 Python
python实现上传样本到virustotal并查询扫描信息的方法
2014/10/05 Python
Python用模块pytz来转换时区
2016/08/19 Python
Python学习小技巧之列表项的推导式与过滤操作
2017/05/20 Python
python实现excel读写数据
2021/03/02 Python
Vue的el-scrollbar实现自定义滚动
2018/05/29 Python
python利用微信公众号实现报警功能
2018/06/10 Python
python引入不同文件夹下的自定义模块方法
2018/10/27 Python
解决阿里云邮件发送不能使用25端口问题
2020/08/07 Python
Nili Lotan官网:Nili Lotan同名品牌
2018/01/07 全球购物
优秀学生干部个人的自我评价
2013/10/04 职场文书
应届生服务员求职信
2013/10/31 职场文书
会计职业生涯规划书
2014/01/13 职场文书
客服专员岗位职责
2015/02/10 职场文书
离婚起诉书范本
2015/05/18 职场文书
高中班主任培训心得体会
2016/01/07 职场文书
分布式锁为什么要选择Zookeeper而不是Redis?看完这篇你就明白了
2021/05/21 Redis
Vue2项目中对百度地图的封装使用详解
2022/06/16 Vue.js