WeChat red envelope algorithm

I have been thinking about how the red envelope algorithm of WeChat is implemented. I found a lot of related technologies on the Internet, but most of them are written in Java. After understanding the principles and ideas, I used php to play it myself. The following summarizes 2 method, please refer to:

The first one: double mean method

The second: line segmentation method

The first two methods are used to achieve the first

1.1 Method ----------------------------

        $money = 100; //100 yuan

        $peoples = 10; //10 people participated

        $min = 1;//The minimum amount is 1 yuan

        

        $rest_amount = $money;

        $rest_peoples = $peoples;

        $getAmount = 0;

        for($i=0;$i<$peoples;$i++){

            //Random range: [1, twice the remaining per capita amount), left closed and right open

            $lastOne = $peoples - 1;

            if($i != $lastOne){

                

                $getAmount = rand($min, ($rest_amount / $rest_peoples * 2));  //精华

                $res[$i] = $getAmount;

                $rest_amount = $rest_amount - $getAmount;

                $rest_peoples--;

            }else{

                $res[$i] = $rest_amount; //This is not the same as theirs (the last person is the remaining amount, preventing insufficient or exceeding the total amount)

            }

        }

        

        echo '<pre>';

        print_r($res);

        echo array_sum($res);

        the;

Let's take a look at the results:

result 1


 Result 2:


 Conclusion: I feel that the random result is not as good as the initial WeChat; look at the following method:

        $total=100;//Total amount of red envelopes 

        $num=10;// Divide into 10 red envelopes, support 10 people to receive randomly

        $min=1;//Everyone can receive at least 1 yuan 

         

        $data = [];

        for ($i=1;$i<$num;$i++) 

        { 

            $safe_total=($total-($num-$i)*$min)/($num-$i);//Random safe upper limit Deduct the remaining minimum amount, half of the maximum, random

            $money=mt_rand($min*100,$safe_total*100)/100; 

            $total=$total-$money; 

            $data[$i] = $money;

        } 

        $data[$num] = $total;

        

        

        echo '<pre>';

        print_r($data);

        echo array_sum($data);

        the;

The result is as follows:


 or:


 It seems that this kind of result is still close to the result of WeChat, and there is rarely a situation where 1 yuan is the lowest;

//----------------The second method (line segmentation method)-------------

We can imagine the total amount of red envelopes as a long line segment, and the amount each person grabs is the sub-line segments split from this main line segment. Determined by the "cut point". When N people grab red envelopes together, N-1 cutting points need to be determined.

Therefore, when N people grab a red envelope with a total amount of M, we need to do N-1 random operations to determine N-1 cutting points. The random range interval is (1, M).

After all the cutting points are determined, the length of the sub-line segment is also determined. In this way, when everyone comes to grab the red envelope, they only need to receive the red envelope amount equivalent to the length of the sub-line segment in sequence.

 

        $total=100;//Total amount of red envelopes

        $num=10;// Divide into 10 red envelopes, support 10 people to receive randomly

        $min=1;//Everyone can receive at least 1 yuan

         

        $data = $money = [];

        for ($i=0;$i<$num;$i++)

        {

            $data[$i] = mt_rand($min,$total);

        }

        $sum = array_sum($data);

        $last = $num-1;

        for($k=0;$k<$last;$k++){ //0~8

            $money[$k] = round(($data[$k] / $sum) * $total,2);

        }

        

        $money[$last] = $total - array_sum($money);

        

        echo '<pre>';

        print_r($data);

        echo '<pre>';

        print_r($money);

        echo array_sum($money);

        the;

 The result is as follows:


 or


 This line segmentation method feels that the data is random and improvised. At present, these two methods are used. If there are any shortcomings, please give us more advice and make progress together.

thanks

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326007677&siteId=291194637