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 相关文章推荐
解决windows下Sublime Text 2 运行 PyQt 不显示的方法分享
Jun 18 Python
Python合并字符串的3种方法
May 21 Python
浅谈python多线程和队列管理shell程序
Aug 04 Python
Python continue继续循环用法总结
Jun 10 Python
pyqt5 禁止窗口最大化和禁止窗口拉伸的方法
Jun 18 Python
django中SMTP发送邮件配置详解
Jul 19 Python
用Pelican搭建一个极简静态博客系统过程解析
Aug 22 Python
Ubuntu下Python+Flask分分钟搭建自己的服务器教程
Nov 19 Python
Python利用matplotlib绘制约数个数统计图示例
Nov 26 Python
Python内置类型性能分析过程实例
Jan 29 Python
windows、linux下打包Python3程序详细方法
Mar 17 Python
Python进程间的通信之语法学习
Apr 11 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
php mysql数据库操作类
2008/06/04 PHP
提交表单后 PHP获取提交内容的实现方法
2016/05/25 PHP
PHP身份证校验码计算方法
2016/08/10 PHP
[原创]php正则删除html代码中class样式属性的方法
2017/05/24 PHP
php post换行的方法
2020/02/03 PHP
Javascript入门学习资料收集整理篇
2008/07/06 Javascript
JavaScript 捕获窗口关闭事件
2009/07/26 Javascript
一些主流JS框架中DOMReady事件的实现小结
2011/02/12 Javascript
禁用键盘上的(全局)指定键兼容iE、Chrome、火狐
2013/05/14 Javascript
JS冒泡事件的快速解决方法
2013/12/16 Javascript
angularjs学习笔记之双向数据绑定
2015/09/26 Javascript
使用jQuery制作遮罩层弹出效果的极简实例分享
2016/05/12 Javascript
js 基础篇必看(点击事件轮播图的简单实现)
2016/08/20 Javascript
Vuex简单入门
2017/04/19 Javascript
Element-UI Table组件上添加列拖拽效果实现方法
2018/04/14 Javascript
Vue Prop属性功能与用法实例详解
2019/02/23 Javascript
vue使用codemirror的两种用法
2019/08/27 Javascript
vue 解决provide和inject响应的问题
2020/11/12 Javascript
Python实现端口复用实例代码
2014/07/03 Python
Python爬取网易云音乐热门评论
2017/03/31 Python
Java及python正则表达式详解
2017/12/27 Python
Flask模拟实现CSRF攻击的方法
2018/07/24 Python
Python中asyncio与aiohttp入门教程
2018/10/16 Python
详解Django项目中模板标签及模板的继承与引用(网站中快速布置广告)
2019/03/27 Python
如何基于Python Matplotlib实现网格动画
2020/07/20 Python
Django nginx配置实现过程详解
2020/09/10 Python
python Gabor滤波器讲解
2020/10/26 Python
利用HTML5中的Canvas绘制一张笑脸的教程
2015/05/07 HTML / CSS
canvas实现烟花的示例代码
2020/01/16 HTML / CSS
Bibloo奥地利:购买女装、男装、童装、鞋和配件
2018/10/18 全球购物
应届专科生个人的自我评价
2014/01/05 职场文书
社会实践活动总结报告
2014/04/29 职场文书
美食节策划方案
2014/05/26 职场文书
2014年教育工作总结
2014/11/26 职场文书
学者《孟子》名人名言
2019/08/09 职场文书
导游词之天下银坑景区
2019/11/21 职场文书