• 【Python】可设置抽奖者权重的抽奖脚本


    功能描述

    抽奖系统包含如下特点:
    1、可给不同抽奖者设置不同的权重
    2、先从价值高的奖品开始抽
    3、已经中奖的人,不再参与后续的抽奖

    代码

    第一个数字表示某一个用户的中奖编号,第二个数字表示该用户的中奖权重。
    名单.txt内容为:

    1:20
    2:10
    3:8
    4:6
    5:6
    6:3
    7:2
    8:1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    main.py内容为:

    # 抽奖工具
    # -*- coding:utf-8 -*-
    from random import choice
    
    def read_name_list(txt_name):
        with open(txt_name, 'r', encoding='utf-8') as f:
            txt_list = f.readlines()
        for i in range(len(txt_list)):
            txt_list[i] = txt_list[i].rstrip('\n')
        return txt_list
    
    def lottery_draw(name_list, prize_box):
        full_number = []
        for name in name_list:
            number, weight = name.split(':')
            full_number += [number] * int(weight)
        for prize in prize_box:
            luck_number = choice(full_number)
            print('【{}】的中奖用户编号为:{}'.format(prize, luck_number))
            full_number = [i for i in full_number if i != luck_number]
    
    if __name__ == '__main__':
        # 导入名单
        name_list = read_name_list('名单.txt')
        # 设置奖项
        prize_box = ['汽车', '电脑', '杯子', '香蕉', '5毛红包']
        # 抽奖
        lottery_draw(name_list, prize_box)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    运行结果如下:

    【汽车】的中奖用户编号为:5
    【电脑】的中奖用户编号为:1
    【杯子】的中奖用户编号为:3
    【香蕉】的中奖用户编号为:25毛红包】的中奖用户编号为:6
    
    • 1
    • 2
    • 3
    • 4
    • 5

    验证

    加一个统计函数statistics、修改下lottery_draw的输入输出,然后抽奖1000000次,看看结果是否和我们设想的一样不同用户中奖权重不同。
    main.py完整代码如下:

    # 抽奖工具
    # -*- coding:utf-8 -*-
    from random import choice
    from collections import Counter
    
    def read_name_list(txt_name):
        with open(txt_name, 'r', encoding='utf-8') as f:
            txt_list = f.readlines()
        for i in range(len(txt_list)):
            txt_list[i] = txt_list[i].rstrip('\n')
        return txt_list
    
    def lottery_draw(name_list, prize_box, res):
        full_number = []
        for name in name_list:
            number, weight = name.split(':')
            full_number += [number] * int(weight)
        for prize in prize_box:
            luck_number = choice(full_number)
            full_number = [i for i in full_number if i != luck_number]
            res.append(prize+':'+luck_number)
        return res
    
    def statistics(res):
        prize_cal = {'汽车':[], '电脑':[], '杯子':[], '香蕉':[], '5毛红包':[]}
        for i in res:
            prize, luck_number = i.split(':')
            prize_cal[prize].append(luck_number)
        for prize, number in prize_cal.items():
            print('【{}】的各用户中奖次数:{}'.format(prize, Counter(number)))
    
    
    if __name__ == '__main__':
        # 导入名单
        name_list = read_name_list('名单.txt')
        # 设置奖项
        prize_box = ['汽车', '电脑', '杯子', '香蕉', '5毛红包']
        # 验证抽奖系统
        res = []
        for i in range(1000000):
            # 抽奖
            res = lottery_draw(name_list, prize_box, res)
        # 统计数据
        statistics(res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    结果为:

    【汽车】的各用户中奖次数:Counter({'1': 356978, '2': 178116, '3': 143076, '5': 107189, '4': 107141, '6': 53638, '7': 35943, '8': 17919})
    【电脑】的各用户中奖次数:Counter({'1': 262385, '2': 192168, '3': 160879, '5': 125696, '4': 125308, '6': 65905, '7': 44822, '8': 22837})
    【杯子】的各用户中奖次数:Counter({'2': 189568, '1': 180131, '3': 173171, '4': 144363, '5': 143846, '6': 82818, '7': 56424, '8': 29679})
    【香蕉】的各用户中奖次数:Counter({'3': 173540, '2': 170010, '4': 162484, '5': 162387, '1': 111469, '6': 104839, '7': 75181, '8': 40090})5毛红包】的各用户中奖次数:Counter({'5': 173954, '4': 173772, '3': 157203, '6': 139308, '2': 136231, '7': 103678, '1': 58633, '8': 57221})
    
    • 1
    • 2
    • 3
    • 4
    • 5

    可以看出以下结论:

    • 通过第一行可以发现,数字之间出现的比例是和我们设置的权重是一样。例如1出现次数约等于2的两倍、45的出现次数相近且均为6的两倍。说明中奖数字出现的概率和预设权重是一样的。
    • 通过后面的行可以发现,对于权重大的数字(例如1),即使第一个奖品没中奖,大概率会在前几个奖品中奖,所以最后一个奖品里1出现的次数很少,因为1基本都是前面出现了。所以权重大的数字优先中价值高的奖品,和设想的一样。
    • 对于权重小的数字,例如78,不管是哪一个奖品,出现次数都是最小的,说明这些数字中奖概率低。原因也很简单,因为中奖数字的个数是小于奖品数量的,所以权重小的数字中奖概率低,很可能5个奖品里都抽不到它们。如果设置为8个奖品的话,那么末尾的奖品78出现次数就会很高,因为此时中奖数字的个数等于奖品数量,所有数字都100%中奖,那么权重小的数字基本上都是中价值低的小奖。例如下面是8个奖品时的实验结果:
      【汽车】的各用户中奖次数:Counter({'1': 357293, '2': 178396, '3': 142964, '4': 106969, '5': 106885, '6': 53787, '7': 35860, '8': 17846})
      【电脑】的各用户中奖次数:Counter({'1': 262439, '2': 191894, '3': 160317, '4': 125823, '5': 125372, '6': 66868, '7': 44747, '8': 22540})
      【杯子】的各用户中奖次数:Counter({'2': 189590, '1': 179792, '3': 172228, '4': 144894, '5': 144557, '6': 82114, '7': 57173, '8': 29652})
      【香蕉】的各用户中奖次数:Counter({'3': 173294, '2': 170689, '4': 162112, '5': 162085, '1': 111105, '6': 105137, '7': 75643, '8': 39935})5毛红包】的各用户中奖次数:Counter({'5': 174098, '4': 173631, '3': 158224, '6': 138613, '2': 135805, '7': 103940, '1': 58826, '8': 56863})
      【空气】的各用户中奖次数:Counter({'6': 201214, '7': 162491, '4': 156446, '5': 156151, '3': 117426, '8': 95013, '2': 87502, '1': 23757})
      【垃圾】的各用户中奖次数:Counter({'7': 282600, '6': 225701, '8': 187694, '5': 99963, '4': 99165, '3': 60536, '2': 38211, '1': 6130})
      【一巴掌】的各用户中奖次数:Counter({'8': 550457, '7': 237546, '6': 126566, '4': 30960, '5': 30889, '3': 15011, '2': 7913, '1': 658})
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
  • 相关阅读:
    Java EE——计算机工作原理
    前端培训丁鹿学堂:js面试之新增数据类型有几个
    taro 兼容支付宝小程序和微信小程序<六>-- 自定义密码或验证码输入框组件的input 自动获取焦点(ios支付宝小程序怎么隐藏input的光标)
    centos软件设置开机启动的方式
    golang 中 sync.Mutex 的实现
    老司机 - 今天去加油
    Linux/shell基础命令
    【服务器数据恢复】SAN LUN映射出错导致文件系统数据丢失的数据恢复案例
    线性表01- 数组与简易接口设计
    架构实战文档全套集齐了
  • 原文地址:https://blog.csdn.net/weixin_38705903/article/details/128065246