024号文書

主にプログラミング

まとめて合成するか?1体ずつ合成するか? 確率分布

問題

Note: まとめて合成するか?1体ずつ合成するか? 期待値と分散 と同一の問題です。

パズドラのようにモンスターを強化するために他のモンスターを合成するゲームに関する問題です。 簡単のため、以下のモデルについて考察します。

  • 強化対象のモンスターをAとします
  • Aに合成されるモンスターはすべて同一種類のモンスターであり、それをBとします
  • あなたはBを30体所持しています
  • 一度の合成で合成可能なBの最大数は5です
  • 一度の合成について、確率0.6でその合成は大成功します。確率0.4でその合成は成功します
  • 各合成が大成功するか成功するかは独立に判定されます
  • 所持しているBが0体になるまで、あなたはAにBを合成できます(合成回数に制限は存在しません)
  • Aに経験値の上限は存在しません

このモデルの肝は「30体所持しているBをどのように分割してAに合成するか」です。

考察

1体ずつ合成する場合の確率分布、2体ずつ合成する場合の確率分布、3体ずつ合成する場合の確率分布、4体ずつ合成する場合の確率分布、5体ずつ合成する場合の確率分布について考察します。

準備

以下の記法を導入します。

  •  f_k(i):  k 体ずつ合成する場合に、大成功するBの数が i 体である確率とします
    •  i k の倍数でない場合、 f_k(i) = 0 です

理論式

 30/k 回のベルヌーイ試行なので、 f_k は二項分布のPMFとなります。

 f_k(ki) = {}_{30}C_i 0.6^{i} \cdot 0.4^{30/k - i}

グラフ

理論式だけでは、イメージが湧きにくいので、Pythonで確率分布のグラフを描画します。

グラフを描画するPythonスクリプト

グラフの描画にMatplotlibを使います。 また、二項分布のPMFscipy.stats.binomを用いて計算します。

 f_kのグラフを描画する関数を以下の通り定義します。

import numpy as np
from scipy.stats import binom
import matplotlib.pyplot as plt

M = 30
P = 0.6

def plot_dist(k):
  L = M // k
  x = np.arange(L + 1) * k
  y = binom.pmf(
      k=np.arange(L + 1),
      n=L,
      p=P
  )
  fig = plt.figure().subplots(1, 1)
  fig.plot(
      x,
      y,
      'bo',
      ms=8
  )
  fig.vlines(x, 0, y, colors='b', lw=5, alpha=0.5)
  plt.xlabel('大成功したBの数')
  plt.show()

描画結果

plot_dist(1)

1体ずつ合成する場合の確率分布
1体ずつ合成する場合の確率分布

plot_dist(2)

2体ずつ合成する場合の確率分布
2体ずつ合成する場合の確率分布

plot_dist(3)

3体ずつ合成する場合の確率分布
3体ずつ合成する場合の確率分布

plot_dist(4)

4体ずつ合成する場合の確率分布
4体ずつ合成する場合の確率分布

plot_dist(5)

5体ずつ合成する場合の確率分布
5体ずつ合成する場合の確率分布

 k が大きくなるにつれてハイリスク・ハイリターンになる様子が視覚的に分かります。