zoukankan      html  css  js  c++  java
  • 通过二分查找实现抽奖活动

    一、项目背景

    最近开始找工作了,重新梳理一下之前做的抽奖活动项目;
    1、 后台设置好奖品信息以及奖品概率;
    2、 然后对奖品进行排序,比如奖品1:'电动车'  34 奖品2:'毛巾一条', 18,奖品3:'面粉一袋', 20 奖品4:'肥皂一块', 12   奖品5:'自行车', 15 奖品6: '奔驰车', 1
    3、 按照奖品1  奖品2  奖品3  奖品4  奖品5 奖品6 这种顺序进行依次入库,这样是保证前端生成抽奖页面时,奖品是按照我们的奖品顺序进行顺时针填充信息;
    4、 当前端抽奖页面抽奖按钮时,异步请求后端获取到奖品,然后进行页面展示;

    二、后端功能代码

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author:supery
    
    import bisect, random
    class WeightRandom:
        def __init__(self, items):
            print('数据库取出的格式化的奖品信息:', items)
            items.sort(key=self.prize_sort)
            print('快排之后的奖品信息: ', items)
            weights = [w for _, w in items]
            print('概率作为权重:',weights)
            self.prize = [x for x, _ in items]
            self.total = sum(weights)
            self.acc = list(self.accumulate(weights))
    
        def accumulate(self, weights):  # 累和.如accumulate([10,40,50])->[10,50,100]
            cur = 0
            for w in weights:
                cur = cur + w
                print('累加:',cur)
                yield cur
    
        def prize_sort(self,elem):
            return elem[1]
    
        def __call__(self):
            rn = random.uniform(0, self.total)
            ran = bisect.bisect_right(self.acc, rn)
            print('随机生成的浮点数: ',rn,)
            print('索引位置: ',ran,)
            return self.prize[ran]
    
    def takeSecond(elem):
        return elem[1]
    
    
    
    if __name__ == '__main__':
        """
        [
            (奖品, 概率),
            (奖品, 概率),
            (奖品, 概率),
            (奖品, 概率),
        ]
        """
    
        wr = WeightRandom([
            ('电动车', 34),
            ('毛巾一条', 18),
            ('面粉一袋', 20),
            ('肥皂一块',12 ),
            ('自行车', 15),
            ('奔驰车', 1),
        ])
        print('累加之后的权重列表: ',wr.acc)
        print('权重对应的奖品信息: ',wr.prize)
        print('获得的奖品获奖: 【%s】'%wr.__call__())

    三、执行结果

    C:Python3python.exe D:/xxx.py
    数据库取出的格式化的奖品信息: [('电动车', 34), ('毛巾一条', 18), ('面粉一袋', 20), ('肥皂一块', 12), ('自行车', 15), ('奔驰车', 1)]
    快排之后的奖品信息:  [('奔驰车', 1), ('肥皂一块', 12), ('自行车', 15), ('毛巾一条', 18), ('面粉一袋', 20), ('电动车', 34)]
    概率作为权重: [1, 12, 15, 18, 20, 34]
    累加: 1
    累加: 13
    累加: 28
    累加: 46
    累加: 66
    累加: 100
    累加之后的权重列表:  [1, 13, 28, 46, 66, 100]
    权重对应的奖品信息:  ['奔驰车', '肥皂一块', '自行车', '毛巾一条', '面粉一袋', '电动车']
    随机生成的浮点数:  88.83932955637896
    索引位置:  5
    获得的奖品获奖: 【电动车】
    
    Process finished with exit code 0

    四、代码说明

    1. 首先从数据库获取到该活动的所有奖品信息,将奖品名称作为元组一个元素,奖励概率作为元组第二个元素;
    2. 之后通过sort进行元组排序,从小到大进行排序,这样后续进行累加权重奖品概率最小的一定是在第一位,概率越大的奖品排列越靠后;
    3. 通过列表表达式,分别获取到奖品名称和奖品概率,生成奖品列表和权重列表;
    4. 通过迭代器累和将奖品的概率进行累加生成一个列表,默认值为0 比如accumulate([10,40,50])->[10,50,100]  0+10=10  10+40=50 50+50=100
       这样是保证随机生成一个浮点数时一定是在权限累和列表中;
    5. 然后通过random uniform方法随机生成一个浮点数,范围是0~100随机不包含100
    6. 最后通过二分查找将将累和列表作为查询列表,浮点数作为比较的值,从右往左依次进行比较,浮点数小于右侧的数值时则返回其索引位置;
    7. 获取到索引在奖品列表中进行查找奖品名称,整个抽奖过程完成!

      

  • 相关阅读:
    centos7 双网卡设置(先NAT和后桥接)
    centos7 nginx搭建及其反向代理
    centos7 出现please make your choice from 1 to enter..
    centos7 keepalive双机热备~
    多线程【转】
    多进程的基本使用--multiprocessing 【转】
    http--一次完整的HTTP事务是怎样一个过程?【转】
    【转】Python操作MongoDB
    文件操作
    Log4j 日志操作包配置详解
  • 原文地址:https://www.cnblogs.com/supery007/p/10883495.html
Copyright © 2011-2022 走看看