u++の備忘録

大相撲の巴戦は最初に戦う2人が有利

 9月場所で千秋楽前に豪栄道が優勝を決めました。純粋に嬉しいです。

 そういえば先場所の千秋楽、巴戦が発生しそうな状況でした。巴戦は一見平等に見えて、実力が同等の場合、実は最初に戦う2人が有利です。

mathtrain.jp

 確率的に計算すると、最初に戦う2人が優勝する確率が5/14、残った1人は4/14です。ただ少し直感的に分かりづらい部分もあり、今回は実際に巴戦を何回も実行するプログラムを書いて実験してみました。

# -*- coding: utf-8 -*-

import random
import collections

PLAYERS_NUM = 3
POWER = PLAYERS_NUM * [100]
result = [] # 結果集計用のリスト
REPEAT = 140000

# 対戦
def Battle(POWER_1, POWER_2):
    prob_win_1 = POWER_1 / (POWER_1 + POWER_2)
    prob_judge = random.random()   
    if prob_win_1 > prob_judge:
        return True
    else:
        return False

for i in range(REPEAT):
    check = True #終了判定用の変数
    # 初期設定
    win_count = 1
    player_1 = 0
    player_2 = 1
    last_winner = 2 #最初に戦わないplayer
    reserve_player = []    
    for j in range(2, PLAYERS_NUM):
        reserve_player.append(j)
    
    while check:
        if Battle(POWER[player_1], POWER[player_2]):
            winner = player_1
            loser = player_2
            player_2 = reserve_player[0]
        else:
            winner = player_2
            loser = player_1
            player_1 = reserve_player[0]
        reserve_player.pop(0)
        reserve_player.append(loser)
        #終了判定
        if last_winner == winner:
            win_count += 1            
            if win_count == PLAYERS_NUM - 1:
                check = False
        else:
            last_winner = winner
            win_count = 1
            
    result.append(winner)

count_dict = collections.Counter(result)
for i in range(PLAYERS_NUM):
    print(str(i) + "の勝率:" + str(count_dict[i] / REPEAT))

 実行結果は以下の通りです。乱数を使っているので、細かな値は変動します。

0の勝率:0.3558428571428571
1の勝率:0.3577571428571429
2の勝率:0.2864

 0と1が最初に戦う力士です。5/14 = 0.3571... , 4/14 = 0.2857... なので、確率的な計算結果とほぼ合致しています。