百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

Python技巧!3分钟学会永不重复的随机点名和微信红包算法

wptr33 2025-03-25 18:07 30 浏览

喜欢的条友记得关注、点赞、转发、收藏,你们的支持就是我最大的动力源泉。

前期基础教程:

「Python3.11.0」手把手教你安装最新版Python运行环境

讲讲Python环境使用Pip命令快速下载各类库的方法

Python启航:30天编程速成之旅(第2天)-IDE安装

【Python教程】JupyterLab 开发环境安装


前言

在职场和校园中,随机点名红包分配是高频需求!你是否遇到过传统工具功能单一、分配不公的痛点?本文用Python打造两大神器,代码可直接复制使用,更有超详细原理拆解,新手也能秒懂!


一、永不重复的随机点名器

1.1 场景痛点

老师上课点名总重复?晨会抽奖有人连续中奖?核心需求:公平随机,且不连续选中同一人!

1.2 代码实现

import random

class RandomRollCall:
    def __init__(self, candidates):
        self.candidates = candidates  # 候选人名单
        self.last_pick = []        # 记录上一次选中的人

    def pick(self):
        # 排除上一次选中的人,生成候选名单
        valid_list = [name for name in self.candidates if name not in self.last_pick]

        # 如果候选名单为空(如只有1人),则重置为原始名单
        if not valid_list:
            valid_list = self.candidates.copy()
        # 随机选择并更新记录
        chosen = random.choice(valid_list)
        self.last_pick.append(chosen)

        return chosen

1.3 案例演示

场景1:课堂点名

students = ["小明", "小美", "张三", "李四", "王五"]
roll_call = RandomRollCall(students)

# 模拟连续点名5次
for _ in range(5):
    print(roll_call.pick())

运行结果:

场景2:仅1人特殊情况

single = ["CEO"]
roll_call = RandomRollCall(single)
print(roll_call.pick())  # 输出:CEO
print(roll_call.pick())  # 仍输出:CEO(因无其他人可选)

运行结果:

1.4 原理精讲

  • 动态候选名单:每次排除上次结果,确保不重复
  • 自动重置机制:当候选名单为空时恢复原始名单,避免报错

二、微信同款拼手气红包算法

2.1 需求拆解

  • 金额约束:每人至少0.01元,总和等于总金额
  • 随机性:金额波动大,增加趣味性

2.2 代码实现(微信同款思路)

def wechat_red_envelope(total, num):
    # 将金额转为分计算,避免浮点误差
    total_cents = int(round(total * 100))
    if num <=0 or total_cents < num * 1:
        raise ValueError("金额过少或人数错误")
    
    amounts = []
    remaining_cents, remaining_num = total_cents, num
    
    # 为前n-1人随机分配金额
    for _ in range(num - 1):
        # 核心算法:随机上限=剩余金额-剩余人数*1分(保证后续分配)
        max_amt = remaining_cents - (remaining_num - 1) * 1
        current_amt = random.randint(1, max_amt)
        amounts.append(current_amt)
        remaining_cents -= current_amt
        remaining_num -= 1
    
    # 最后一人拿剩余金额
    amounts.append(remaining_cents)
    random.shuffle(amounts)  # 打乱顺序,避免越后面金额越小
    
    # 转换回元,并保留两位小数
    return [amt / 100.0 for amt in amounts]

2.3 案例演示

场景1:5人抢50元红包

result = wechat_red_envelope(50, 5)
print("分配结果:", result)
print("验证总和:", sum(result))  # 输出:50.0

输出示例

场景2:极端测试(0.02元分3人,每人不足0.01元)

result = wechat_red_envelope(0.02, 3)
print("分配结果:", [round(amt, 2) for amt in result])
print("验证总和:", sum(result))  # 输出:10.0

输出示例

场景3:极端测试(0.03元分3人,每人0.01元)

result = wechat_red_envelope(0.03, 3)
print("分配结果:", [round(amt, 2) for amt in result])
print("验证总和:", sum(result))  # 输出:10.0

运行结果:

2.4 原理解析

  • 整数运算:所有金额转为分计算,避免浮点误差
  • 动态上限:每次分配确保剩余金额足够后续每人1分
  • 随机打乱:避免列表顺序影响金额分布

三、进阶优化技巧

3.1 点名器支持权重

为特定学生设置更高概率(如学号靠后的易被抽中):

def weighted_pick(self):
    # 权重示例:按名单顺序递增
    weights = [i+1 for i in range(len(self.candidates))]
    valid_weights = [w for idx,w in enumerate(weights) if self.candidates[idx] != self.last_pick]
    chosen = random.choices(valid_list, weights=valid_weights, k=1)[0]
    return chosen

3.2 红包金额波动控制

添加参数控制最大金额倍数:

def wechat_red_envelope(total, num, max_multiple=2):
    ...
    max_amt = min(max_amt, (remaining_cents // remaining_num) * max_multiple)
    ...

四、避坑指南

  1. 浮点数精度:红包计算务必转为整数运算
  2. 查重率优化:变量命名个性化(如 valid_list→candidate_pool)
  3. 合规性:代码注释中避免敏感词,示例用虚拟数据

结语

本文代码可直接复制到PyCharm或VSCode中运行,关注我,获取更多Python职场效率工具!

喜欢的条友记得关注、点赞、转发、收藏,你们的支持就是我最大的动力源泉。

相关推荐

oracle数据导入导出_oracle数据导入导出工具

关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...

继续学习Python中的while true/break语句

上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个else解...

python continue和break的区别_python中break语句和continue语句的区别

python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...

简单学Python——关键字6——break和continue

Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...

2-1,0基础学Python之 break退出循环、 continue继续循环 多重循

用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...

Python 中 break 和 continue 傻傻分不清

大家好啊,我是大田。今天分享一下break和continue在代码中的执行效果是什么,进一步区分出二者的区别。一、continue例1:当小明3岁时不打印年龄,其余年龄正常循环打印。可以看...

python中的流程控制语句:continue、break 和 return使用方法

Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...

L017:continue和break - 教程文案

continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...

作为前端开发者,你都经历过怎样的面试?

已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...

面试被问 const 是否不可变?这样回答才显功底

作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...

2023金九银十必看前端面试题!2w字精品!

导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。答案:CSS的盒模型是用于布局和定位元素的概念。它由内容区域...

前端面试总结_前端面试题整理

记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...

由浅入深,66条JavaScript面试知识点(七)

作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录由浅入深,66条JavaScript面试知识点(一)由浅入深,66...

2024前端面试真题之—VUE篇_前端面试题vue2020及答案

添加图片注释,不超过140字(可选)1.vue的生命周期有哪些及每个生命周期做了什么?beforeCreate是newVue()之后触发的第一个钩子,在当前阶段data、methods、com...

今年最常见的前端面试题,你会做几道?

在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...