请见下面的更新说明...
我正在编写一个Python模拟程序,将任意数量的虚拟玩家分配到一个目标池中的一个目标。这些目标有两个不同的稀缺程度比例:prop_high
和 prop_low
,它们大约是3:1的比例。
例如,如果有16个玩家和4个目标,或者8个玩家和4个目标,则这两个目标池看起来像这样:
{'A': 6, 'B': 6, 'C': 2, 'D': 2}
{'A': 3, 'B': 3, 'C': 1, 'D': 1}
...其中目标A和B的发生频率是C和D的3倍。6 + 6 + 2 + 2 = 16,这对应于模拟中的玩家数量,非常好。
我希望有一个与玩家数量相等的目标池,并且分配方式是prop_low
目标的三倍左右有prop_high
目标。
如何构建一个分配算法,使其按照粗略或近似比率(可以处理四舍五入)?
更新:
假设有8个玩家,则2到8个目标的分布应该如下所示(用星号表示prop_high
玩家):
A B C D E F G H
2 6* 2
3 6* 1 1
4 3* 3* 1 1
5 3* 2* 1 1 1
6 2* 2* 1* 1 1 1
7 2* 1* 1* 1 1 1 1
8 1* 1* 1* 1* 1 1 1 1
这些数字与球员无关。例如,当有5个进球和8名球员时,进球A和B在池中占据较高比例(分别为3和2),而进球C、D和E则更为罕见(每个进球仅出现1次)。
当进球数为奇数时,最后的prop_high会比其他进球类型少一个数量。随着进球数接近球员数,每个prop_high项目都会逐渐减少一个,直到最后,在池中存在每个进球类型的一种。
下面我对池的高低端进行数量分配,然后根据进球数与球员数之间的接近程度对高端进行调整,依照这种方法可以很好地处理8名球员的情况(池中的进球数始终为8),但仅限于此。
我确信有一种更好的、更符合Python规范的方式来处理这种算法,我相信这是一种相对常见的设计模式。我只是不知道从哪里开始搜索以找到处理这种结构的更优雅的方法(而非目前使用的暴力方法)。
import string
import math
letters = string.uppercase
num_players = 8
num_goals = 5
ratio = (3, 1)
prop_high = ratio[0] / float(sum(ratio)) / (float(num_goals)/2)
prop_low = ratio[1] / float(sum(ratio)) / (float(num_goals)/2)
if num_goals % 2 == 1:
is_odd = True
else:
is_odd = False
goals_high = []
goals_low = []
high = []
low = []
# Allocate the goals to the pool. Final result will be incorrect.
count = 0
for i in range(num_goals):
if count < num_goals/2: # High proportion
high.append(math.ceil(prop_high * num_players))
goals_high.append(letters[i])
else: # Low proportion
low.append(math.ceil(prop_low * num_players))
goals_low.append(letters[i])
count += 1
# Make adjustments to the pool allocations to account for rounding and odd numbers
ratio_high_total = len(high)/float(num_players)
overall_ratio = ratio[1]/float(sum(ratio))
marker = (num_players / 2) + 1
offset = num_goals - marker
if num_players == num_goals:
for i in high:
high[int(i)] -= 1
elif num_goals == 1:
low[0] = num_players
elif ratio_high_total == overall_ratio and is_odd:
high[-1] -= 1
elif ratio_high_total >= overall_ratio: # Upper half of possible goals
print offset
for i in range(offset):
index = -(int(i) + 1)
high[index] -= 1
goals = goals_high + goals_low
goals_quantities = high + low
print "Players:", num_players
print "Types of goals:", num_goals
print "Total goals in pool:", sum(goals_quantities)
print "High pool:", goals_high, high
print "Low pool:", goals_low, low
print goals, goals_quantities
print "High proportion:", prop_high, " || Low proportion:", prop_low
prop_low
目标数量的prop_high
目标。顺序并不重要;最终所有目标都将是随机的。 - Andrew