Python实现抢红包分配算法【递归】

算法:   

红包金额是随机的,但是每一轮你能抢到的红包金额,最高不会超过剩下红包的均值的二倍。

若只有一个人,则获得所有剩下的金额。

递归实现:

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!")
    
        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值