いっぽんの猟銃のむこうに (DAIZOじいさんとGun)

ヌルめの技術メモとか。フリーランスやってます (http://acez.jp/)

6分割コンプガチャの出現確率はおおむね混一色くらい

いま話題のコンプガチャの確率を数学的に証明してくださったエントリを見て。(http://doryokujin.hatenablog.jp/entry/2012/05/09/034209)

うーん……正直数学ガール見て実際お手上げめいた似非理系プログラマの僕には数式みるだけで目眩が……

というわけでシミュレーションコード書いてみました。はい。力技です。

  1. いわゆるガチャをコンプするのに何回、回す必要があるか
  2. 1.を単一の超出現確率の低いカード(いわゆるスーパーレア)1枚に置き換えるとどのくらいの出現確率になるか

をざっくり求めてみたものです。Python 2.7。

#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import sys, random

# 試行回数(デフォルト)
AVG_TRIALS = 10

"""
M枚分割されているコンプガチャ1枚を、単純に
非常に出現率の低いスーパーレアカード1枚に移行したとして、
損にならない程度の出現確率を求める
"""
def main(part):
    # ガチャコンプリートまでの平均回数を求める
    cnt = 0
    for i in range(0, AVG_TRIALS):
        cnt += getCompGachaCount(part)

    # ガチャコンプリート平均回数
    comp_times = cnt / AVG_TRIALS

    # 上で求めた回数回したとして、ギリギリ出現する程度になる
    # スーパーレアカード出現確率の平均を求める
    cnt = 0.00
    for i in range(0, AVG_TRIALS):
        cnt += getSuperRareOdds(comp_times)

    # 対応するスーパーレアの確率"
    s_rare_odds = cnt / AVG_TRIALS

    return (comp_times, s_rare_odds)


'''
part 枚分割のガチャをコンプするのに必要な回数を求める
'''
def getCompGachaCount(part):
    # 分割カードを準備
    p = (int)(part)
    list = [False] * p  # 初期状態
    comp = [True] * p   # コンプ状態

    # 全部コンプするまで回す
    cnt = 0
    while(list != comp):
        i = random.randint(0, part - 1)
        list[i] = True
        cnt += 1

    return cnt


'''
times 回数回してレアなカードがギリギリ出現する程度の
スーパーレアカードの出現確率を求める
'''
def getSuperRareOdds(times):
    i = 0
    # 10%から0.1%刻みで減らしていく
    ### (ここの処理、もっといい方法ないか???)
    odds = 0.1
    while(True):
        i += 1
        # レアカードが出現した場合
        if (random.random() <= odds):
            odds -= 0.01
            i = 0
            continue

        # 規定回数回しきった場合、その時の確率値を返す
        if times <= i:
            return odds


# main method
if __name__ == '__main__':
    argv = sys.argv
    argc = len(argv)
    if (argc != 3):
        print 'usage: python %s [part] [trials]' % argv[0]
        quit()

    part = (int)(argv[1])
    AVG_TRIALS = (int)(argv[2])

    timesum = 0.0
    s_raresum = 0.0
    for i in range(0, AVG_TRIALS):
        times, s_rare = main(part)
        timesum += times
        s_raresum += s_rare

    print "試行 %d回" % AVG_TRIALS
    print "ガチャコンプ平均回数 %f回" % (float)(timesum / AVG_TRIALS)
    print "対応スーパーレア平均確率 %g" % (float)(s_raresum / AVG_TRIALS)

で、以下が実行結果です。それぞれ4枚分割、6枚分割、9枚分割、12枚分割。

tkizmMBA:~ teru$ python CompGachaMigrateToSuperRare.py 4 100
試行 100回
ガチャコンプ平均回数 7.790000回
対応スーパーレア平均確率 0.089075

tkizmMBA:~ teru$ python CompGachaMigrateToSuperRare.py 6 100
試行 100回
ガチャコンプ平均回数 14.280000回
対応スーパーレア平均確率 0.077232

tkizmMBA:~ teru$ python CompGachaMigrateToSuperRare.py 9 100
試行 100回
ガチャコンプ平均回数 25.080000回
対応スーパーレア平均確率 0.056412

tkizmMBA:~ teru$ python CompGachaMigrateToSuperRare.py 12 100
試行 100回
ガチャコンプ平均回数 36.810000回
対応スーパーレア平均確率 0.038563

なんとなく怪しい部分がいくつかありますが、まあ参考程度に。

結論としては、6枚分割コンプガチャは麻雀の役で言えば混一色(6.1%)より出やすい程度、ってことですかね……
(http://www2.odn.ne.jp/~cbm15900/html/y99.html)

こうして値だけ見れば、思ってたより意外に出るような気がしますが、射幸心煽られちゃってるんですかねえ……


※このシミュレーションは全カードの出現確率は均等であるという前提です※