Python利用帶權(quán)重隨機(jī)數(shù)解決抽獎和游戲爆裝備問題
關(guān)于帶權(quán)隨機(jī)數(shù)
為了幫助理解,先來看三類隨機(jī)問題的對比:
1.已有n條記錄,從中選取m條記錄,選取出來的記錄前后順序不管。
實(shí)現(xiàn)思路:按行遍歷所有記錄,約隔n/m條取一個數(shù)據(jù)即可
2.在1類情況下,還要求選取出來的m條記錄是隨機(jī)排序的
實(shí)現(xiàn)思路: 給n條記錄,分別增加一列標(biāo)記,值為隨機(jī)選取的1至n之間的不重復(fù)數(shù)據(jù)。
3.區(qū)別于1,2類問題, 如果記錄是有權(quán)重的,如何結(jié)合權(quán)重去隨機(jī)選取。 比如A的權(quán)重為10, B的權(quán)重股為5, C的權(quán)重為1, 則隨機(jī)選取4個時可能應(yīng)該出現(xiàn)AABB。
第3類問題便是本文重點(diǎn)了。
實(shí)現(xiàn)思路: 以 A:10, B:5, C:1 三條記錄上隨機(jī)選取4條為例,(是否以權(quán)重排序這個無所謂)
對于
A 10
B 5
C 1
首先,將第n行的數(shù)值賦為第n行加第n-1行的,遞歸執(zhí)行,如下:
A 10
B 15
C 16
然后每次從[1,16]隨機(jī)選取一個數(shù),如果落在[1,10]之間,則選取A,如果落在(10,15]之間則選B,如果落在(16,16]之間則選取C, 圖示如下,誰占的區(qū)間大(權(quán)重高),被選上的概率更大。

在抽獎和游戲爆裝備中的運(yùn)用
帶權(quán)隨機(jī)在游戲開發(fā)中重度使用,各種抽獎和爆裝備等.
運(yùn)營根據(jù)需要來配置各個物品出現(xiàn)的概率.
今天要說的這個帶權(quán)隨機(jī)算法思想很簡單,就是"把所有物品根據(jù)其權(quán)重構(gòu)成一個個區(qū)間,權(quán)重大的區(qū)間大.可以想象成一個餅圖. 然后,扔骰子,看落在哪個區(qū)間,"
舉個栗子,有個年終抽獎,物品是iphone/ipad/itouch.
主辦方配置的權(quán)重是[('iphone', 10), ('ipad', 40), ('itouch', 50)].
用一行代碼即可說明其思想,即random.choice(['iphone']*10 + ['ipad']*40 + ['itouch']*50).
下面,我們寫成一個通用函數(shù).
#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:#遍歷找出骰子所在的區(qū)間
if n<w:
break
n -= w
return x
print weighted_random([('iphone', 10), ('ipad', 40), ('itouch', 50)])
上面的代碼夠直觀,不過細(xì)心的會發(fā)現(xiàn),每次都會計算total,每次都會線性遍歷區(qū)間進(jìn)行減操作.其實(shí)我們可以先存起來,查表就行了.利用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()
相關(guān)文章
Python基于Twilio及騰訊云實(shí)現(xiàn)國際國內(nèi)短信接口
這篇文章主要介紹了Python基于Twilio及騰訊云實(shí)現(xiàn)國際國內(nèi)短信接口,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06
Python多線程threading join和守護(hù)線程setDeamon原理詳解
這篇文章主要介紹了Python多線程threading join和守護(hù)線程setDeamon原理詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-03-03
Python編碼規(guī)范擺脫P(yáng)ython編碼噩夢
Python 中編碼問題,一直是很多 Python 開發(fā)者的噩夢,盡管你是工作多年的 Python 開發(fā)者,也肯定會經(jīng)常遇到令人神煩的編碼問題,收藏這篇文章以后你可以不用再Google2021-10-10
pandas中read_excel()函數(shù)的基本使用
在Python的數(shù)據(jù)處理庫pandas中,read_excel()函數(shù)是用于讀取Excel文件內(nèi)容的強(qiáng)大工具,本文就來介紹一下如何使用,具有一定的參考價值,感興趣的可以了解一下2024-03-03
關(guān)于spring的@Bean注解放入引用Bean中初始化失敗分析
這篇文章主要介紹了關(guān)于spring的@Bean注解放入引用Bean中初始化失敗分析,Spring的@Bean注解用于告訴方法,產(chǎn)生一個Bean對象,然后這個Bean對象交給Spring管理,產(chǎn)生這個Bean對象的方法Spring只會調(diào)用一次,需要的朋友可以參考下2023-07-07
使用python如何實(shí)現(xiàn)泛型函數(shù)
這篇文章主要介紹了使用python如何實(shí)現(xiàn)泛型函數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
Python學(xué)習(xí)小技巧之列表項(xiàng)的排序
這篇文章主要給大家介紹了Python學(xué)習(xí)小技巧之列表項(xiàng)排序的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友們可以參借鑒,下面跟著小編一起來學(xué)習(xí)學(xué)習(xí)吧。2017-05-05

