Python利用带权重随机数解决抽奖和游戏爆装备问题
作者:mattkang 发布时间:2023-09-21 10:16:43
关于带权随机数
为了帮助理解,先来看三类随机问题的对比:
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, 图示如下,谁占的区间大(权重高),被选上的概率更大。
在抽奖和游戏爆装备中的运用
带权随机在游戏开发中重度使用,各种抽奖和爆装备等.
运营根据需要来配置各个物品出现的概率.
今天要说的这个带权随机算法思想很简单,就是"把所有物品根据其权重构成一个个区间,权重大的区间大.可以想象成一个饼图. 然后,扔骰子,看落在哪个区间,"
举个栗子,有个年终抽奖,物品是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()
猜你喜欢
- import cv2import numpy as npimport matplotlib.pyplot as plt# Grayscale
- 如果我有一个数据集,他的某个列名下面的value很长,我们需要筛选出,所有列名中value值字符串大于20的数据集。其实比较简单啦,一句代码
- 本文实例讲述了Python生成器定义与简单用法。分享给大家供大家参考,具体如下:一、什么是生成器在Python中,由于受到内存的限制,列表容
- Python 基础教程之包和类的用法建立一个文件夹filePackage 在filePackage 文件夹内创建 __init__.py 有
- 详解 Python中LEGB和闭包及装饰器LEGB L>E>G?BL:local函数内部作用域E:enclosing函数内部与内
- numpy.random.shuffle在做将caffe模型和预训练的参数转化为tensorflow的模型和预训练的参数,以便微调,遇到如下
- permute(dims)将tensor的维度换位。参数:参数是一系列的整数,代表原来张量的维度。比如三维就有0,1,2这些dimensio
- 在python中,普通的列表list和numpy中的数组array是不一样的,最大的不同是:一个列表中可以存放不同类型的数据,包括int、f
- 我们已经在Python运算中看到Python最基本的数学运算功能。此外,math包补充了更多的函数。当然,如果想要更加高级的数学功能,可以考
- 一、基本概述目前电脑上已经下载了MongoDB数据库、navicat for mongodb作为mongoDB的可视化工具,形如navica
- 在本文上两篇中,我们学习了脚本语言 VBScript 的变量、函数、过程和条件语句,本篇将继续给大家介绍 VBScipt 的循环语句,并对脚
- Python 环境下文件的读取问题,请参见拙文 Python基础之文件读取的讲解这是一道著名的 Python 面试题,考察的问题是,Pyth
- 如何自动登陆京东?我们先来看一下京东的登陆页面,如下图所示:【插入图片,登陆页面】登陆框就是右面这一个框框了,但是目前我们遇到一个困呐,默认
- 在php中判断一个文件或目录是否存在,大家通常都会想到is_file和file_exists两个函数。但这两个函数再判断一个远程url文件是
- MySQL 如何从表中取出随机数据 以前在群里讨论过这个问题,比较的有意思.mysql的语法真好玩. 他们原来都想用P
- 普通爬虫正常流程:数据来源分析发送请求获取数据解析数据保存数据环境介绍python 3.8pycharm 2021专业版【付费VIP完整版】
- 之前对bottle做过不少的介绍,也写过一些文章来说明bottle的缺点,最近发现其实之前有些地方说的不太公平,所以趁此机会也来更正一下。&
- 在SQL SERVER中,你可能需要获得当前日期和计算一些其他的日期,例如,你的程序可能需要判断一个月的第一天或者最后一天。你们大部分人大概
- 目录演示地址:关于程序开发环境资源和依赖包NASA TV feed 流Python第三方库完整代码演示地址:https://replit.c
- innewDropList = [9,10,11,12,22,50,51,60,61]newDB = newDB[newDB['gr