微信红包算法
功能概述
该函数 lineSegmentOptimize
用于模拟微信红包的分配算法。它将一个固定金额的红包分成指定数量的随机份额,并确保每个份额的金额为整数,同时总金额与原红包金额一致。
代码分析
输入参数
$Moneys
: 红包总金额。$userNums
: 红包分配的总人数。$isEveryHave
: 可选参数,表示是否每个人至少有一个单位的金额,默认为1
。
逻辑流程
- 进行输入参数的合法性校验。
- 根据
$isEveryHave
的值决定切割点的范围。 - 如果
userNums
为 1,则直接将全部金额分给一个人。 - 使用
array_rand
从数组中随机取出切割点,将红包划分为多个区间。 - 返回划分后的红包金额数组。
优化后的代码
<?php
function lineSegmentOptimize($Moneys, $userNums, $isEveryHave = 1)
{
// 参数合法性检查
if ($Moneys <= 0 || $userNums <= 0) {
return ['code' => -3, 'msg' => '红包金额或拆红包总人数不合法'];
}
if ($isEveryHave && $userNums > $Moneys) {
return ['code' => -4, 'msg' => '红包数量不足'];
}
// 单个红包的特殊情况处理
if ($userNums == 1) {
return ['code' => 0, 'msg' => 'success', 'redbag' => [$Moneys]];
}
// 初始化变量
$userMoney = [];
$MoneysArr = $isEveryHave ? array_fill(1, $Moneys - 1, 0) : array_fill(0, $Moneys + 1, 0);
// 生成切割点
$cutPoints = array_rand($MoneysArr, $userNums - 1);
sort($cutPoints);
// 根据切割点划分红包金额
$lastVal = 0;
foreach ($cutPoints as $randPoint) {
$userMoney[] = $randPoint - $lastVal;
$lastVal = $randPoint;
}
$userMoney[] = $Moneys - $lastVal;
return ['code' => 0, 'msg' => 'success', 'redbag' => $userMoney];
}
代码功能说明
参数合法性检查
- 确保红包总金额和人数都是正数。
- 如果选择了每个人至少有一个单位的金额且人数超过总金额,返回错误信息。
特殊情况处理
- 如果红包仅分配给一个人,直接返回总金额。
随机切割点的生成
- 使用
array_rand
生成多个不重复的随机切割点,并确保区间包括首尾。
- 使用
红包金额的计算
- 通过切割点的差值将红包划分成多个部分,最后返回一个包含各部分金额的数组。
使用方法
调用函数时,传入红包总金额 $Moneys
,分配的人数 $userNums
,以及可选的 isEveryHave
参数(默认为 1
,即每人至少有一份)。例如:
$result = lineSegmentOptimize(100, 5);
print_r($result);
总结
该算法通过随机生成切割点将红包总金额划分为多个部分,并确保划分后的金额分布均匀且总和与原红包金额一致。代码经过优化后,结构更清晰,逻辑更合理,适合实际应用场景中的红包分配需求。