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实现系统状态监测和故障转移实例方法
Nov 18 Python
python递归实现快速排序
Aug 18 Python
Python3中内置类型bytes和str用法及byte和string之间各种编码转换 问题
Sep 27 Python
python 含子图的gif生成时内存溢出的方法
Jul 07 Python
详解pandas数据合并与重塑(pd.concat篇)
Jul 09 Python
8种用Python实现线性回归的方法对比详解
Jul 10 Python
django admin.py 外键,反向查询的实例
Jul 26 Python
python数据预处理方式 :数据降维
Feb 24 Python
python 回溯法模板详解
Feb 26 Python
python文件排序的方法总结
Sep 13 Python
Python读取多列数据以及用matplotlib制作图表方法实例
Sep 23 Python
使用bandit对目标python代码进行安全函数扫描的案例分析
Jan 27 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 db类库进行数据库操作
2009/03/19 PHP
PHP Array交叉表实现代码
2010/08/05 PHP
PHP图片加水印实现方法
2016/05/06 PHP
PHP实现PDO操作mysql存储过程示例
2019/02/13 PHP
KindEditor在php环境下上传图片功能集成的方法示例
2020/07/20 PHP
删除重复数据的算法
2006/11/23 Javascript
jquery+json 通用三级联动下拉列表
2010/04/19 Javascript
php的文件上传入门教程(实例讲解)
2014/04/10 Javascript
Javascript 事件冒泡机制详细介绍
2016/10/10 Javascript
jQuery中Nicescroll滚动条插件的用法
2016/11/10 Javascript
利用PM2部署node.js项目的方法教程
2017/05/10 Javascript
关于TypeScript模块导入的那些事
2018/06/12 Javascript
javascript关于“时间”的一次探索
2019/07/24 Javascript
Python 代码性能优化技巧分享
2012/08/07 Python
python快速排序代码实例
2013/11/21 Python
python实现ftp客户端示例分享
2014/02/17 Python
Django imgareaselect手动剪切头像实现方法
2015/05/26 Python
python中seaborn包常用图形使用详解
2019/11/25 Python
python deque模块简单使用代码实例
2020/03/12 Python
PyTorch加载自己的数据集实例详解
2020/03/18 Python
xadmin使用formfield_for_dbfield函数过滤下拉表单实例
2020/04/07 Python
CSS3 对过渡(transition)进行调速以及延时
2020/10/21 HTML / CSS
多视角3D可旋转的HTML5 Logo动画
2016/03/02 HTML / CSS
节省高达65%的城市景点费用:Go City
2019/07/06 全球购物
金讯Java笔试题目
2013/06/18 面试题
函授本科毕业自我鉴定
2013/10/09 职场文书
追悼会主持词
2014/03/20 职场文书
园林设计专业毕业生求职信
2014/03/23 职场文书
房地产开发项目建议书
2014/05/16 职场文书
软件工程毕业生自荐信
2014/07/04 职场文书
个人查摆剖析材料
2014/10/04 职场文书
2015毕业实习推荐信
2015/03/23 职场文书
培训班开班主持词
2015/07/02 职场文书
2016年机关单位节能宣传周活动总结
2016/04/05 职场文书
2019年个人工作总结范文
2019/03/25 职场文书
你会写请假条吗?
2019/06/26 职场文书