概述:
经历一周赶项目,终于项目上线之后就闲下来。突然今天回想起之前一次面试的有趣的面试题——“你处理转盘抽奖自定义概率有什么好的思路?”当年太年轻了,只是说到公倍数,含含糊糊的回答让面试官不太满意。如今,想起了,理清思路发现也不困难,在此分享一下做法。
准备:
主要的抽奖逻辑是抽取随机数来进行抽奖,同时用区间的不同来代表不同的奖项。该注释的地方都注释了,如果还是看不懂的读者可以私下问我。(注意:方法中echo出来的只是为了方便测试方法运行的过程来方便读者理解,自行修改删去就好。)
分析:
主要代码:
/**
* 修改自义定概率抽奖算法
* @param $coupon_list = array('prize_name1' => 'probability1','prize_name2'=>'probability2','prize_name3'=>'probability3',……)
* @return prize_name
*/
public function lotter_test($coupon_list=array('a' => '1/3','b'=>'1/5','c'=>'1/8')) {
//第一部分为处理输入的奖项概率数组
foreach($coupon_list as $name=>$value){
$exp = explode("/",$value); //分隔分数
$numerator[$name] = $exp[0]; //分子
$denominator[$name] = $exp[1]; //分母
}
$common_multiple = 1; //初定义公倍数
foreach($denominator as $value){
$common_multiple *= $value; //计算公倍数
}
foreach($denominator as $name=>$value){
$new_list[$name] = $common_multiple/$value*$numerator[$name];//获得每一个奖项分别占公倍数的多少份
}
$count = array_sum($new_list); //补充其他情况(各奖项总概率为100%)
$other = $common_multiple - $count;//得出数组中的其他情况占公倍数的多少份
$new_list = array_merge($new_list,array('other' => $other)); //添加其他情况到数组中
//第二部分为抽取随机数来进行抽奖
$luck_num = mt_rand(0, $common_multiple);
echo 'luck_num='. $luck_num;
echo '</br>';
$_counter = 0;
foreach($new_list as $name => $value) {
$_counter += $value;
echo '$_counter='. $_counter;
echo '$name='. $name;
if ($luck_num <= $_counter) {
return $name;
}
echo '</br>';
}
}
测试部分:
public function test11(){
$arr =array('a'=>'1/9999','b'=>'1/888','c'=>'1/3');
echo '</br>The result is ' . $this ->lotter_test($arr);
}
测试返回的结果:
luck_num=7403940
$_counter=2664$name=a
$_counter=32661$name=b
$_counter=8911773$name=c
The result is c