计算试验次数以获得唯一性

2024-04-24 22:15:59 发布

您现在位置:Python中文网/ 问答频道 /正文

给出下表

Type     Chance Number of unique elements 
common   30.00%  21
Uncommon 30.00%  27
Rare     20.00%  32
Ultra    15.00%  14
Epic     5.00%   10

是否有一种方法可以使用python脚本计算在所有类型中获得X数量的唯一元素所需的平均测试数(即5个我不拥有的元素,无论它们是常见的还是不常见的等等)


Tags: of方法脚本元素类型numbertypeelements
1条回答
网友
1楼 · 发布于 2024-04-24 22:15:59

好的,这就是解决方案:

from numpy.random import multinomial
import numpy as np

class UniqueElements:
    def __init__(self, type_dist, unique_elements):
        self.type_dist = type_dist
        self.unique_elements = unique_elements
        self.unique_elements_dist = [[1.0 / n for i in range(n)] for n in unique_elements]
        self.init_items()
        
    def pickone(self, dist):
        return np.where(multinomial(1, dist) == 1)[0][0]
    
    def init_items(self):
        self.items = np.zeros((len(self.type_dist), max(self.unique_elements)), dtype=int)
    
    def draw(self):
        item_type = self.pickone(self.type_dist)
        item_number = self.pickone(self.unique_elements_dist[item_type])
        return item_type, item_number
    
    def draw_unique(self, x):
        while (self.items > 0).sum() < x:
            item_type, item_number = self.draw()
            self.items[item_type, item_number] += 1
        return self.items.sum()
    
    def average_for_unique(self, x, n, reset=True):
        tot_draws = 0
        for i in range(n):
            tot_draws += self.draw_unique(x)
            if reset:
                self.init_items()
            else:
                self.items[self.items>1] -= 1

        return tot_draws / n
    
if __name__ == '__main__':
    type_dist = [0.3, 0.3, 0.2, 0.15, 0.05]
    unique_elements = [21, 27, 32, 14, 10]
    ue = UniqueElements(type_dist, unique_elements)
    print(ue.average_for_unique(10, 100000))
        

如果要将每个已完成的“预留”放在一边并继续处理剩余的内容,请按如下所示更改最后一行: print(ue.average_for_unique(10, 100000, reset=False))

注:对于x=5,平均值为5.1;对于x=8,平均值为8.3。这并不奇怪,因为不同类型中有104个独特的元素

为了演示,这是使用Julia编程语言的同一个程序:

using Random

function pickone(dist)
    n = length(dist)
    i = 1
    r = rand()
    while r >= dist[i] && i<n 
        i+=1
    end
    return i
end  

function init_items(type_dist, unique_elements)
    return zeros(Int32, length(type_dist), maximum(unique_elements))
end

function draw(type_dist, unique_elements_dist)
    item_type = pickone(type_dist)
    item_number = pickone(unique_elements_dist[item_type])
    return item_type, item_number
end

function draw_unique(type_dist, unique_elements_dist, items, x)
    while sum(items .> 0) < x
        item_type, item_number = draw(type_dist, unique_elements_dist)
        items[item_type, item_number] += 1
    end
    return sum(items)
end

function average_for_unique(type_dist, unique_elements_dist, x, n, reset=true)
    println("Started computing...")
    items = init_items(type_dist, unique_elements)

    tot_draws = 0
    for i in 1:n
        tot_draws += draw_unique(type_dist, unique_elements_dist, items, x)
        if reset
            items .= 0
        else
            items[items.>1] -= 1
        end
    end

    return tot_draws / n
end
    
type_dist = [0.3, 0.3, 0.2, 0.15, 0.05]
type_dist = cumsum(type_dist)

unique_elements = [21, 27, 32, 14, 10]
unique_elements_dist = [[1 / unique_elements[j] for i in 1:unique_elements[j]] for j in 1:length(unique_elements)]
unique_elements_dist = [cumsum(dist) for dist in unique_elements_dist]

avg = average_for_unique(type_dist, unique_elements_dist, 10, 100000)
print(avg)
    

更长的启动时间,尤其是在下载和编译软件包时。在那之后,它燃烧得很快

有人可以改进Python版本以匹配Julia版本吗?100分赏金

相关问题 更多 >