首页 > 解决方案 > 如何修改 Coupon Collector 问题的 Monte Carlo Simulation 代码

问题描述

我要解决的问题是,如果我每天随机收到 1/5 个优惠券,那么这 5 个优惠券中的每一个需要多少天才能收集到 2 份?

我的代码只检查每张优惠券中的一张而不是两张,但我不确定我可以在哪里进行修改。我编辑了 while True 语句,以在我的 cards_own 语句中包含一个列表,cards_own != [1,1,2,2,3,3,4,4,5,5]但是我的输出根本没有打印出来。我认为也许使用 random.choice 函数会是一个更好的选择。有什么建议吗?

import numpy as np

# number of simulations
n =10000 

# defining function to check if we got all 5 cards indexed from 0 to 4
def all_cards(arr2,arr1=np.array(range(5))):
  return np.array_equal(arr1,arr2)  
days_taken = 0

# performing simulation
for i in range(n):

  # initializing empty list to store card obtained in each day
  cards_own =[]

  # days taken in each simulation
  days =1

  # looping until i get 5 cards and count the days taken for finding average
  while True:
    value = np.random.randint(0,5)
    cards_own.append(value)

    if len(cards_own)>=5:
      if all_cards(arr2=np.array(list(set(cards_own)))):
        days_taken+=days
        break 
    days+=1
  
average = days_taken/n

# recording the result in result with given precision 
result = round(average,2)
print("Average days taken = ",result," days")

标签: pythonnumpymontecarlo

解决方案


所以我认为你可以在这里改变一些事情。首先,您可以将 if 语句更改为 read if len(cards_own) >= 10,因为您需要至少 10 张优惠券才能拥有 2 份所有物品。此外,在您的cards_all函数中,您可以遍历所有可能的优惠券(在本例中为 [0, 4] 并检查数组中的每个优惠券是否至少出现两次(因此您不需要arr2)。喜欢:

for i in range(5):
    if np.sum(arr1 == i) < 2:
        return False
return True

if 语句只是计算元素 i 在数组中出现的次数。此外,您不应该arr1在函数调用中转换为集合,因为集合不能有重复的值,因此检查每张优惠券中的 2 个永远不会像那样工作。希望这会有所帮助!


推荐阅读