ホームページ >バックエンド開発 >PHPチュートリアル >誰もが赤い封筒をつかみ、プログラマーは赤い封筒のアルゴリズムを研究し、赤い封筒をつかむ_PHP チュートリアル
大晦日の一日を通じてWeChatユーザーによって送信された赤い封筒の総数は10億1千万に達し、シェイクインタラクションの数はは 110 億回に達し、赤い封筒の送信数はピーク時に 81 億回/分に達しました。
WeChatの赤い封筒の市場価値はさておき、赤い封筒のアルゴリズム自体も激しい議論を引き起こしています。公式が明確な声明を出していないため、編集者は以下にいくつかの分析も提供します。
データ分析の帝王を初見
ほとんどの人は独自の推測を行いますが、内部のランダム アルゴリズムがわからない場合はそれが唯一の選択肢ですが、ほとんどの人は自分の個人的な調査結果を提供しません。ここに 100 個のサンプルの調査サンプル データがあり、独自の推測を提示します。
1. ウォレットのお金は検閲された正規乱数分布を満たします。大まかに言うと、打ち切り正規分布から乱数を取得し、合計した数値を合計値で割って補正係数を取得し、その後、補正係数にすべての乱数を乗算してレッド エンベロープ値を取得します。
この分布は、平均よりも低い赤いエンベロープがより多くありますが、平均からそれほど離れていないこと、平均を上回る赤いエンベロープはほとんどありませんが、平均よりもはるかに大きい赤いエンベロープがより多く存在することを意味します。
図 1. ウォレットの値とその度数分布ヒストグラムとその正規近似
しかし、分布ヒストグラムを見ると正規分布に従うとは推測できませんが、プログラムの単純さと乱数の合理性を考慮すると、これが最も合理的な推測です。
一般的に後ろにある財布の方が価値が高いです
図 2. ウォレットのシーケンス番号とその値の関係曲線
図2の赤い直線フィッティングから、ウォレット価値の全体的な変化傾向がゆっくりと増加しており、その変化範囲は緑色の点線の上限と下限で区切られたほぼ「チャネル」であることがわかります。 (曲線は、このような従来の「チャネル」で囲むことができます。これは、ルール 1 の合理性を側面から反映しており、乱数が一様に分布していないことを示しています)
このパターンは、別の平均プロットでも見られます。
図3.系列数による平均の変化曲線
サンプルでは、1000 相当の財布が 100 の部分に分割され、平均値は 10 になります。ただし、図 3 では、最後のウォレットの前では平均が 10 未満になっていることがわかります。これは、最初のウォレットの価値が低く、後のウォレットの価値によって引き上げられていることを示しています。値が高くなります。
3. もちろん、平均グラフからは別の法則も明らかになります。つまり、最終的に得た人は幸運にもより多くの絵を描くことができるということです。最後の人は財布に残っているものをすべて受け取り、前の全員の平均は 10 未満であるため、最後の人が平均よりも高いことが少なくとも保証されます。このサンプルでは、ウォレット番号 98 は 35 を引き出し、最後のウォレットは 46 を引き出しました。
要約すると、サンプルに基づいて推測します:
1. ほとんどの場合、引き出したお金は他のお金と同じくらい少額ですが、一度それ以上になると、より多くのお金を得るのがはるかに簡単になります。
2. 財布の裏を引けば引くほど、お金を稼ぐのは簡単になります。
3. 最後の人は不運に見舞われることが多いです。
コメント: これは明らかに非常に実質的な違いであり、編集者はそれを入手するたびに数セントしか支払いません。
2人目の生徒は簡単なPythonコードを書きました
観察によれば、赤い封筒は以下の点を満たしています:
1. お金をもらえない人はいない
2.事前配布はございません
3. お金の変動が大きい
赤い封筒が最初に作成された時点で、配布計画はすでに設定されています。赤い封筒を掴むと、一枚ずつ出てくるだけです。
したがって、Python コードは次のようになります:
リーリーただし、上記のアルゴリズムには 2 つの小さな問題があります:
1. 浮動小数点精度の問題
2.境界値の処理
3人目はインターネット上で流通しているPythonをベースにJava版を書きました
リーリー4 番目の生徒のアルゴリズムは非常に科学的に見えます。
彼はこう考えます:
1. 誰もが赤い封筒を受け取ることができる必要があります。
3. 受け取る赤い封筒の量は人によって異なりますが、あまり異なるものは面白くありません。
4. アルゴリズムは単純である必要があります。そうしないと、Tencent の署名が失敗します。
正式编码之前,先搭建一个递进的模型来分析规律
设定总金额为10元,有N个人随机领取:
N=1
则红包金额=X元;
N=2
为保证第二个红包可以正常发出,第一个红包金额=0.01至9.99之间的某个随机数
第二个红包=10-第一个红包金额;
N=3
红包1=0.01至0.98之间的某个随机数
红包2=0.01至(10-红包1-0.01)的某个随机数
红包3=10-红包1-红包2
……
int j=1; while(j<1000) { int number=10; float total=100; float money; double min=0.01; double max; int i=1; List math=new ArrayList(); while(i<number) { max = total- min*(number- i); int k = (int)((number-i)/2); if (number -i <= 2) {k = number -i;} max = max/k; money=(int)(min*100+Math.random()*(max*100-min*100+1)); money=(float)money/100; total=total-money; math.add(money); System.out.println("第"+i+"个人拿到"+money+"剩下"+total); i++; if(i==number) { math.add(total); System.out.println("第"+i+"个人拿到"+total+"剩下0"); } } System.out.println("本轮发红包中第"+(math.indexOf(Collections.max(math))+1)+"个人手气最佳"); j++; }
输入一看,波动太大,这数据太无趣了!
第1个红包:7.48 元,余额:2.52 元
第2个红包:1.9 元,余额:0.62 元
第3个红包:0.49 元,余额:0.13 元
第4个红包:0.04 元,余额:0.09 元
第5个红包:0.03 元,余额:0.06 元
第6个红包:0.03 元,余额:0.03 元
第7个红包:0.01 元,余额:0.02 元
第8个红包:0.02 元,余额:0 元
改良一下,将平均值作为随机安全上限来控制波动差
int j=1; while(j<1000) { int number=10; float total=100; float money; double min=0.01; double max; int i=1; List math=new ArrayList(); while(i<number) { max = total- min*(number- i); int k = (int)((number-i)/2); if (number -i <= 2) {k = number -i;} max = max/k; money=(int)(min*100+Math.random()*(max*100-min*100+1)); money=(float)money/100; total=total-money; math.add(money); System.out.println("第"+i+"个人拿到"+money+"剩下"+total); i++; if(i==number) { math.add(total); System.out.println("第"+i+"个人拿到"+total+"剩下0"); } } System.out.println("本轮发红包中第"+(math.indexOf(Collections.max(math))+1)+"个人手气最佳"); j++; }
输出结果见下图
第1个红包:0.06 元,余额:9.94 元
第2个红包:1.55 元,余额:8.39 元
第3个红包:0.25 元,余额:8.14 元
第4个红包:0.98 元,余额:7.16 元
第5个红包:1.88 元,余额:5.28 元
第6个红包:1.92 元,余额:3.36 元
第7个红包:2.98 元,余额:0.38 元
第8个红包:0.38 元,余额:0 元
小结:
小编觉得这完全可以理解成一个红包引发的血案,小编仅仅列举了几个,还有一些工程学的同学直接抛出了数学模型、离散函数等等,但是无论算法是简单还是复杂,玩的开心就够了。