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 相关文章推荐
在Django的模型中执行原始SQL查询的方法
Jul 21 Python
浅谈python新手中常见的疑惑及解答
Jun 14 Python
Python中在脚本中引用其他文件函数的实现方法
Jun 23 Python
python奇偶行分开存储实现代码
Mar 19 Python
python利用高阶函数实现剪枝函数
Mar 20 Python
Python中的二维数组实例(list与numpy.array)
Apr 13 Python
Python FTP两个文件夹间的同步实例代码
May 25 Python
Python读取指定日期邮件的实例
Feb 01 Python
python多进程间通信代码实例
Sep 30 Python
简单的Python人脸识别系统
Jul 14 Python
python写文件时覆盖原来的实例方法
Jul 22 Python
Python 绘制多因子柱状图
May 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
当年上海收录机产品生产,进口和价格情况
2021/03/04 无线电
利用Memcached在php下实现session机制 替换PHP的原生session支持
2010/08/21 PHP
php中DOMDocument简单用法示例代码(XML创建、添加、删除、修改)
2010/12/19 PHP
PHP 获取文件权限函数介绍
2013/07/11 PHP
WordPress自定义时间显示格式
2015/03/27 PHP
thinkPHP的表达式查询用法详解
2016/09/14 PHP
PHP实现的链式队列结构示例
2017/09/15 PHP
tp5.1 框架join方法用法实例分析
2020/05/26 PHP
JavaScript 未结束的字符串常量常见解决方法
2010/01/24 Javascript
jQuery EasyUI NumberBox(数字框)的用法
2010/07/08 Javascript
jquery异步调用页面后台方法&amp;#8207;(asp.net)
2011/03/01 Javascript
jQuery的deferred对象使用详解
2011/08/20 Javascript
JS声明变量背后的编译原理剖析
2012/12/28 Javascript
用js判断输入是否为中文的函数
2014/03/10 Javascript
jQuery中parent()方法用法实例
2015/01/07 Javascript
jQuery实现带滚动线条导航效果的方法
2015/01/30 Javascript
javascript宿主对象之window.navigator详解
2016/09/07 Javascript
Bootstrap3多级下拉菜单
2017/02/24 Javascript
使用webpack4编译并压缩ES6代码的方法示例
2019/04/24 Javascript
基于vue写一个全局Message组件的实现
2019/08/15 Javascript
用Python进行一些简单的自然语言处理的教程
2015/03/31 Python
PyQt5 QTableView设置某一列不可编辑的方法
2019/06/25 Python
python输出电脑上所有的串口名的方法
2019/07/02 Python
cProfile Python性能分析工具使用详解
2019/07/22 Python
python实现小程序推送页面收录脚本
2020/04/20 Python
用HTML5制作一个简单的桌球游戏的教程
2015/05/12 HTML / CSS
ghd官网:英国ghd直发器品牌
2018/05/04 全球购物
教师实习期自我鉴定
2013/10/06 职场文书
园长自我鉴定
2013/10/06 职场文书
电子商务专业学生的自我鉴定
2013/11/28 职场文书
学术会议欢迎词
2014/01/09 职场文书
金融管理专业毕业生求职信
2014/03/12 职场文书
小学生爱国演讲稿
2014/04/25 职场文书
不遵守课堂纪律的检讨书
2014/09/24 职场文书
gojs实现蚂蚁线动画效果
2022/02/18 Javascript
国产动画《万圣街》日语配音版制作决定!
2022/03/20 国漫