活动规则实现算法小思
最近有一个开发需求 (签到活动的变种)
需求:用户需要连续的在页面上面签到,签到成功一次则增加一个积分,如果中途有一天没有签到则扣除一个积分.账户不能为负数,账户每次都从不小于零开始计算
问题:想怎么最简单的方法来实现这个功能,最好能在一个表达式解决问题,
然后就得到三个实现方式,
前两个是常规的实现方式
第三个比较特殊的实现方式 一个表达式可以实现功能(达到目标),
用到主要知识点:
1:递归正则表达式.
2:实现算法这边可以理解为<> () 这种的成对抵消, 1 表示< ;0表示>, 10为0,则递归替换(递归正则表达式)所有的成对的10,不成对的最后剩下的肯定是后面是1前面是0.(反过来替换01 则剩下的肯定是前面是1后面就是0). 根据这个特性最后留下0{n}1{m}这样的字符串,那么m的个数(1字符串长度)就是积分数量.
不喜欢多说 直接上代码吧
签到用1 没有签到用0填充 开始生成一些随机用户随机当期内的随机签到,用数组存储,
如果用第三种方法,用单个字段字符串存(1010111)储单个用户签到,否则需要在处理成字符串.
//玩法, 签到的变种 用户需要连续的在页面上面签到,签到成功一次则增加一个积分, //如果中途有一天没有签到则扣除一个积分.账户不能为负数,账户每次都从不小于零开始计算 //假如我们有若干个用户 randUserNum,当前活动周期为 randDayNum 我们先生成一些用户数据和情况 $randUserNum = rand(5,10); $randDayNum = rand(1,6); $users = []; $sersAccount = []; //整理后的用户账户体系 for($i=0;$i<$randUserNum;$i++){ $user = []; for($j=0;$j<$randDayNum;$j++){ $user[] = rand(0,1); } $users[] = $sersAccount[] = $user; unset($user); } //第一种方法 循环去处理 foreach ($users as $key=>$user){ $point = 0; //每个账户都是零 for($i = 0; $i < $randDayNum; $i++){ if($user[$i]){ //如果当前签到了 增加积分 $point += 1; }elseif($point){//如果需要减分 当前账户必须为有积分 就是说活动期间的结算结果都不能负分 $point -= 1; } } $sersAccount[$key]['way_one'] = $point;// 这个算法算出来的积分 } //第二种方法 递归 foreach ($users as $key=>$user){ $sersAccount[$key]['way_two'] = getPoint($user,0); //初始账户为0 } //递归获得累加用户积分 function getPoint($usersigns,$point){ $sign = array_shift($usersigns); //每次取出一个元素 if( $sign !== NULL){ //当最后一个元素的时候终止递归 if($sign){ //如果当前签到了 增加积分 $point +=1; }elseif($point){//如果需要减分 当前账户必须为有积分 就是说活动期间的结算结果都不能负分 $point -=1; } return getPoint($usersigns, $point); } else { return $point; } } //第三种方法 特殊方法 原理 根据当前的规则可以推算出来10其实就是0积分 把所有的10清空 那么 剩下的 1的个数就是积分, //假如 010101010101 就是 替换掉所有的10 就是 01 就是1积分1001100 递归替换掉10 就是0 //当然还有一些其他的字符串处理规则 例如 如果 知道天数不太大 可以直接转换成整形 来处理 就不用str_replace foreach ($users as $key=>$user){ $user_str = implode('', $user); //这一步可以在存储的时候就用字符串存储 //(?R) 这个为正则的递归匹配当前的表达式 类似 <a<b>c<dddeee<asdf>>> $user_str = str_replace('0', '', preg_replace('/1(?R)*0/', '', $user_str)); $sersAccount[$key]['way_three'] = strlen($user_str); //只剩下1111 这样子 有多少个 1 就是多少积分 } file_put_contents('data2.php', var_export($sersAccount,true)); //结果保存下 查看
结果测试
array ( 0 => array ( 0 => 0, 1 => 1, 2 => 1, 3 => 1, 4 => 1, 'way_one' => 4, 'way_two' => 4, 'way_three' => 4, ), 1 => array ( 0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 1, 'way_one' => 1, 'way_two' => 1, 'way_three' => 1, ), 2 => array ( 0 => 0, 1 => 0, 2 => 1, 3 => 1, 4 => 1, 'way_one' => 3, 'way_two' => 3, 'way_three' => 3, ), 3 => array ( 0 => 0, 1 => 1, 2 => 0, 3 => 1, 4 => 0, 'way_one' => 0, 'way_two' => 0, 'way_three' => 0, ), 4 => array ( 0 => 1, 1 => 1, 2 => 1, 3 => 1, 4 => 0, 'way_one' => 3, 'way_two' => 3, 'way_three' => 3, ), 5 => array ( 0 => 1, 1 => 1, 2 => 0, 3 => 1, 4 => 0, 'way_one' => 1, 'way_two' => 1, 'way_three' => 1, ), 6 => array ( 0 => 1, 1 => 1, 2 => 0, 3 => 0, 4 => 0, 'way_one' => 0, 'way_two' => 0, 'way_three' => 0, ), 7 => array ( 0 => 1, 1 => 0, 2 => 0, 3 => 0, 4 => 1, 'way_one' => 1, 'way_two' => 1, 'way_three' => 1, ), )