見出し画像

指スマってどれくらい先攻が有利なの?【Python】

合図に合わせて親指を上げて、上がった指の本数を当てるあのゲーム!
使われる合図は地域によって様々なようですが、一般的には「指スマ」と呼ばれることが多いと思います。

以前、2人で行う指スマがnターン目に終了する確率を求める確率漸化式を解き、先攻が勝つ確率を求めてみた!という内容の記事を書きました。

上記の記事では、気が遠くなるような計算量の漸化式を解いた結果、「2人で行う指スマにおいては、5ターン目で終了する確率が最も高く、先攻が勝つ確率が55%である」という結論が得られました。

この記事を書いた後、「3人以上の指スマの場合はどうなのだろう?」という新たな疑問が思い浮かびました。
2人で行う指スマを解く漸化式ですら超大変だったのに、3人以上の指スマを解く漸化式なんて無理…という感じなので、Pythonでシミュレーションしていきたいと思います。

シミュレーションに使ったPythonのソースコードは以下の通りです。
興味がない方はスキップして頂いて構いません!
変数 n_playersを変更することで、任意の人数の指スマシミュレーションを行うことが出来ます。

import random
import matplotlib.pyplot as plt
import statistics

def play_thumb_sumo_n_players(n_players):
    fingers = [2] * n_players
    turn = 0

    while all(f > 0 for f in fingers):
        attacker = turn % n_players
        defenders = [(attacker + i) % n_players for i in range(1, n_players)]
        attack_number = random.randint(0, sum(fingers[d] for d in defenders))
        defense_number = sum(random.randint(0, fingers[d]) for d in defenders)

        if attack_number == defense_number:
            fingers[attacker] -= 1

        turn += 1

    winner = fingers.index(0) + 1
    return winner, turn

def simulate_thumb_sumo_n_players(n_players, n_simulations):
    player_wins = {f"player{i+1}": 0 for i in range(n_players)}
    turn_distribution = {}

    for i in range(n_simulations):
        winner, turns = play_thumb_sumo_n_players(n_players)
        player_wins[f"player{winner}"] += 1

        # シミュレーションの進捗確認用
        if (i+1) % (n_simulations // 1000) == 0:
            progress = (i+1) / n_simulations * 100  # 進捗をパーセントで計算
            print(f'Progress: {progress:.1f}%')
        
        if turns in turn_distribution:
            turn_distribution[turns] += 1
        else:
            turn_distribution[turns] = 1

    win_rates = [wins * 100 / n_simulations for wins in player_wins.values()]
    max_win_rate = max(win_rates)
    min_win_rate = min(win_rates)
    rate_ratio = max_win_rate / min_win_rate if min_win_rate > 0 else float('inf')

    turns = list(turn_distribution.keys())
    frequencies = [turn_distribution[t] for t in turns]

    plt.bar(turns, frequencies, color='blue')
    plt.xlabel('ターン', fontname="MS Gothic")
    plt.ylabel('データ数', fontname="MS Gothic")
    plt.title(f'{n_players}人で行う指スマの勝敗が決まるターンの度数分布', fontname="MS Gothic")

    # 勝率と勝率の分散をグラフに表示
    y_pos = max(frequencies) * 0.8  # 初期のy座標位置を少し上に調整
    y_offset = max(frequencies) * 0.06  # テキスト間のオフセット

    for i, (player, rate) in enumerate(player_wins.items()):
        plt.text(max(turns) * 0.7, y_pos, f"{player}: {rate / n_simulations * 100:.2f}%", fontsize=12,
                 bbox=dict(facecolor='skyblue', alpha=0.6, boxstyle='round,pad=0.5'))
        y_pos -= y_offset

    # 最大勝率/最小勝率を表示
    plt.text(max(turns) * 0.7, y_pos, f"Rate Ratio (Max/Min): {rate_ratio:.2f}", fontsize=12,
             bbox=dict(facecolor='lightgreen', alpha=0.6, boxstyle='round,pad=0.5'))

    plt.grid(True)
    plt.show()

    return {f"player{i+1}": rate / n_simulations * 100 for i, rate in enumerate(player_wins.values())}

# 実行
win_rates_players = simulate_thumb_sumo_n_players(3, 100000)
print(win_rates_players)

それでは、シミュレーション結果を見ていきたいと思います!

まずは、前回の記事で解いた2人で行う指スマのシミュレーション結果を確認してみましょう!

2人指スマのシミュレーション結果

横軸が指スマが終了したターン数、縦軸が10万回試行中のデータ数です。
右上に表示している水色背景の数字は、先攻(1ターン目で数字を言う)プレイヤーであるplayer1と後攻(2ターン目で数字を言う)プレイヤ―であるplayer2の勝率です。
緑色背景の数字 Rate Ratio (Max/Min)は、勝率の最大値と最小値の比を求めた値です。つまり、先攻と後攻の間でどれくらい不平等が発生しているかの度合いを数値化したものです。

この結果によると、以前に漸化式を解いて求めた結果(先攻の勝率55%)と、ほとんど同じ結果(先攻の勝率55.04%)が得られました!計算ミスがなかったようで良かったです。5ターン目でゲームが終了する確率が最も高いのもグラフから明らかですね。
Rate Ratio (Max/Min)の値は1.22となっていて、先攻の方が後攻より22%程度勝率が高い計算になりますね。


それでは、今回の本題である3人以上で行う指スマのシミュレーション結果を見ていきましょう!

3人指スマのシミュレーション結果

やはり先攻が有利で、1人目のプレイヤーの勝率が36.34%なのに対して、3人目のプレイヤーの勝率は30.43%となっています。Rate Ratio (Max/Min)の値は1.19となっていて、先攻の方が後攻より19%程度勝率が高い計算になりますね。2人のときよりは少し不平等さが減少したみたいです。

ここで注目したいのが、4~6ターン目(上の棒グラフでは、一番左側の3本の棒が表す部分)でゲームが終了する確率が上昇している点です。4ターン目でゲームが終了する場合、1ターン目と4ターン目の両方で1人目のプレイヤーが数字当てに成功してますね。一方で、6ターン目でゲームが終了する場合、3ターン目と6ターン目の両方で3人目のプレイヤーが数字当てに成功してます(ただし、4, 5ターン目でゲームが終了する場合は含まれません)。
つまり、基本的に先攻の方が有利な指スマにおいても、最初に2回連続で数字を当てて勝利する確率に絞って考えると、後攻の方が有利だということが分かります。
これは、ターンが後に進むにつれて、残っている指の総数が少ないため、数字を当てやすいことが原因だと考えられます。
残念ながら、7ターン目以降を見ると後攻がどんどん不利になっていくことが伺えます。


次に4, 5人で行う指スマのシミュレーション結果も見ていきましょう!

4人指スマのシミュレーション結果
5人指スマのシミュレーション結果

この辺りまで来ると、ゲーム終了に必要なターン数もかなり増えてきますね。
先攻と後攻の不平等さを表す Rate Ratio (Max/Min)の値も徐々に減っていて、5人指スマでは17%程度の差に抑えられています。また、5人指スマまで来ると、2連続で数字を当てなくても最初の15ターンくらいまでは、ほぼ平等にゲームが進むことが分かります。


最後に10人で行う指スマのシミュレーション結果を見て終わりにしましょう!結果がこちら!

10人指スマのシミュレーション結果

ここまで来るとゲームを終了させるのがとても大変です…
200ターンくらいまでは続く覚悟を持っておかないといけませんね。
Rate Ratio (Max/Min)の値は、さらに減少して1.15となりました。ただ、ここまで人数を増やしても完全な平等には程遠いことが分かりました。何人でやっても後攻に不利なゲームですね。

以上、指スマをシミュレーションして先攻の有利度合いを調べた結果でした!

この記事が参加している募集

この記事が気に入ったらサポートをしてみませんか?