算法:
红包金额是随机的,但是每一轮你能抢到的红包金额,最高不会超过剩下红包的均值的二倍。
若只有一个人,则获得所有剩下的金额。
递归实现:
import random
total_money = 100
people_count = 10
# 红包派发递归算法
def compute(i,result):
#最后一位,获得剩下所有红包
if i == 1:
result.append(total_money-sum(result))
return result
# 规则:获取0.1 ~ 剩余红包均值*2 的随机值
flag_num = ((total_money - sum(result))/i)*2
tmp_money = random.uniform(0.1,flag_num)
result.append(tmp_money)
return compute(i-1,result)
if __name__ == '__main__':
# random.seed(0)
result = []
print(compute(people_count,result))
print("done!")
运行输出:
[0.3697853859424588, 7.3728028174278695, 4.296486283847702, 24.836398381674968, 1.1473666460544087, 6.962220916822089, 10.97743138809708, 14.719119093423886, 22.362077252637103, 6.956311834072423]
done!
重复10000次,并将结果记录进 csv:
import random
import csv
total_money = 100
people_count = 10
repeat_num = 10000
# 红包派发递归算法
def compute(i,result):
#最后一位,获得剩下所有红包
if i == 1:
result.append(total_money-sum(result))
return result
# 规则:获取0.1 ~ 剩余红包均值*2 的随机值
flag_num = ((total_money - sum(result))/i)*2
tmp_money = random.uniform(0.1,flag_num)
result.append(tmp_money)
return compute(i-1,result)
# 记录到csv表格
def write2csv(rows):
with open('result.csv','w+',newline='')as f:
f_csv = csv.writer(f)
f_csv.writerows(rows)
if __name__ == '__main__':
# 进行repeat_num次循环试验
total_result = []
for i in range(repeat_num):
# random.seed(0) 取消这行注释则每一次运行结果都一样
result = []
total_result.append(compute(people_count,result))
write2csv(total_result)
print("done!")
得到结果如:
补充:
根据微信红包的随机算法是怎样实现的? - 知乎与揭秘微信红包:架构、抢红包算法、高并发和降级方案 - 尚码园,有改进版:
import random
import csv
total_money = 100
people_count = 10
repeat_num = 10000
bottom_money = 0.01
# 红包派发递归算法-基础版
def compute(i,result):
#最后一位,获得剩下所有红包
if i == 1:
result.append(total_money-sum(result))
return result
# 规则:获取下水位(0.01) ~ 上水位(剩余红包均值*2)的随机值
flag_num = ((total_money - sum(result))/i)*2
tmp_money = random.uniform(bottom_money,flag_num)
result.append(tmp_money)
return compute(i-1,result)
# 红包派发递归算法-加强版:浮动上水位
def compute_pro(i,result):
#最后一位,获得剩下所有红包
if i == 1:
result.append(total_money-sum(result))
return result
# flag_num: 剩余红包均值*2的金额
flag_num = ((total_money - sum(result))/i)*2
# max_num: 保证剩下的人至少0.01的金额
max_num = total_money - bottom_money*i
top_money = min(flag_num,max_num)
# 上下水位之间取随机数
tmp_money = random.uniform(bottom_money,top_money)
result.append(tmp_money)
return compute(i-1,result)
# 红包派发递归算法-至臻加强版:浮动上水位+取余运算
def compute_pro2(i,result):
#最后一位,获得剩下所有红包
if i == 1:
result.append(total_money-sum(result))
return result
# flag_num: 剩余红包均值*2的金额
flag_num = ((total_money - sum(result))/i)*2
# max_num: 保证剩下的人至少0.01的金额
max_num = total_money - bottom_money*i
top_money = min(flag_num,max_num)
# 上下水位之间取随机数
tmp_money = random.uniform(bottom_money,top_money)
# 随机数取余,小于0.01则置为0.01
if top_money%tmp_money<bottom_money:
result.append(bottom_money)
else:
result.append(tmp_money)
return compute(i-1,result)
# 记录到csv表格
def write2csv(rows):
with open('result.csv','w+',newline='')as f:
f_csv = csv.writer(f)
f_csv.writerows(rows)
if __name__ == '__main__':
# 进行repeat_num次循环试验
total_result = []
for i in range(repeat_num):
# random.seed(0)
result = []
total_result.append(compute_pro2(people_count,result))
write2csv(total_result)
print("done!")