さて
今回は確率のお話です。


「ロト7」の1等、同じ売り場から3口も当選

なんてニュースが最近有ったので
いろいろなギャンブルの確率が
どのくらいなのかを求めてみたくなりました。

解説動画はこちら



まずは競馬からです。

競馬は16-18頭の馬の中から
着順を当てる仕組みです。

馬券は正式には
勝ち馬投票券と言うらしいです。

16頭18頭だてでそれぞれを求めました。

確率計算にはPythonを用いますので
ライブラリをインポートします。

import math
import itertools
こちらを用います。

さて、まずは単勝から
単に1着を当てるもの

確率は
# 16頭
print('{0}/{1}'.format(1, 16))
print('{0:.5}%'.format(1/16*100))
1/16
6.25%
# 18頭
print('{0}/{1}'.format(1, 18))
print('{0:.5}%'.format(1/18*100))
1/18
5.5556%

次は複勝
1-3着に入る馬を当てます。

予想した馬が1位でも3位でも良いので
単純に単勝の3倍になります。
# 16頭
print('{0}/{1}'.format(3, 16))
print('{0:.5}%'.format(3/16*100))
3/16
18.75%
# 18頭
print('{0}/{1}'.format(3, 18))
print('{0:.5}%'.format(3/18*100))
3/18
16.667%


複勝であれば
6回に1回は当たるという確率ですね。

ただし払い戻しは平均2倍程度なので
あまり美味しくはありません。

お次は枠連
18頭の馬は9の枠に入れられます。
それぞれ1-2頭ほどで構成され
その枠での順位を当てるというものです。

9枠の中から2枠を選ぶというものです。

Pythonでの
組み合わせの求め方は2通りありますが
len(list(itertools.combinations(range(9),2)))

math.factorial(9) // (math.factorial(9 - 2) * math.factorial(2))
どちらであっても36通りです。

ということで確率は
waku = math.factorial(9) // (math.factorial(9 - 2) * math.factorial(2))
print('{0}/{1}'.format(1, waku))
print('{0:.5}%'.format(1/waku*100))
1/36
2.7778%

となります。


お次は馬単と馬連
選んだ2頭が1-2着になる組み合わせで
馬単は1-2着をそのまま当てる
馬連は1-2,2-1どちらでも良いという買い方です。

当然
馬連は馬単の2倍の確率になります。

馬練:
# 16頭
umaren= math.factorial(16) // (math.factorial(16 - 2) * math.factorial(2))
print('{0}/{1}'.format(1, umaren))
print('{0:.5}%'.format(1/umaren*100))
1/120
0.83333%
# 18頭
umaren= math.factorial(18) // (math.factorial(18 - 2) * math.factorial(2))
print('{0}/{1}'.format(1, umaren))
print('{0:.5}%'.format(1/umaren*100))
1/153
0.65359%

馬単:
# 16頭
umatan= math.factorial(16) // math.factorial(16 - 2)
print('{0}/{1}'.format(1, umatan))
print('{0:.5}%'.format(1/umatan*100))
1/240
0.41667%
# 18頭
umatan= math.factorial(18) // math.factorial(18 - 2)
print('{0}/{1}'.format(1, umatan))
print('{0:.5}%'.format(1/umatan*100))
1/306
0.3268%


お次はワイド
3着以内に入る組み合わせのうち2つを
それらの着順に依らず順不同で予想するものです。

1-2 , 1-3 , 2-3着になれば良いので
単純に馬連の3倍の確率になります。

# 16頭
wide = math.factorial(16) // (math.factorial(16 - 2) * math.factorial(2))
print('{0}/{1}'.format(3, wide))
print('{0:.5}%'.format(3/wide*100))
3/120
2.5%
# 18頭
wide = math.factorial(18) // (math.factorial(18 - 2) * math.factorial(2))
print('{0}/{1}'.format(3, wide))
print('{0:.5}%'.format(3/wide*100))
3/153
1.9608%


次は3連
3連単と3連複でそれぞれ
3連単:1着・2着・3着になる組み合わせを着順通りに予想する
3連複:1着・2着・3着になる組み合わせを順不同で予想する

3連複:は組み合わせ(16C3 , 18C3)
3連単:は順列(16P3 , 18P3)でもとめることになります。


3連複:
# 16頭
sanrenhuku = math.factorial(16) // (math.factorial(16 - 3) * math.factorial(3))
print('{0}/{1}'.format(1, sanrenhuku))
print('{0:.5}%'.format(1/sanrenhuku*100))
1/560
0.17857%
# 18頭
sanrenhuku = math.factorial(18) // (math.factorial(18 - 3) * math.factorial(3))
print('{0}/{1}'.format(1, sanrenhuku))
print('{0:.5}%'.format(1/sanrenhuku*100))
1/816
0.12255%


3連単:
# 16頭
sanrentan= math.factorial(16) // math.factorial(16 - 3)
print('{0}/{1}'.format(1, sanrentan))
print('{0:.5}%'.format(1/sanrentan*100))
1/3360
0.029762%
# 18頭
sanrentan= math.factorial(18) // math.factorial(18 - 3)
print('{0}/{1}'.format(1, sanrentan))
print('{0:.5}%'.format(1/sanrentan*100))
1/4896
0.020425%

このくらいの確率になると
でたらめに選んで買っても
5千回に1回しか当たりません。

そうとう当たらないので
当てるには絞り込みの技術が必要になってきます。

競馬の最後はWIN5
JRAが指定する5つのレース
それぞれの1着を予想するものです。

単勝の5乗ですね。

その確率は
win5 = 18**5
print('{0}/{1}'.format(1, win5))
print('{0:.10F}%'.format(1/win5*100))
1/1889568
0.0000529221%

約190万分の1の確率です。
当てた際の
払戻金の想定額が2億円ほどで

宝くじなどの確率が
1000万分の1の確率で
同じくらいの金額なので

WIN5の方が期待値は上かと思います。


競馬の確率の高さは

複勝>単勝>枠連>ワイド>馬連>馬単>3連複>3連単>WIN5

になります。

次は宝くじのうち
ロト6です。

ロト6は1-43まで数字のうち
本数字6個と1個のボーナス数字
計7個の数字を選択して当てるものです。

1-5等まであります。

まずは1等

本数字6個すべて一致

なので単純に
43C6 となります。
この数はロト6のベースとなる数です。

求め方は
loto_base = math.factorial(43) // (math.factorial(43 - 6) * math.factorial(6))
print('{0}/{1}'.format(1, loto_base))
print('{0:.10f}%'.format(1/loto_base*100))
1/6096454
0.0000164030%

1等は約600万分の1の確率となります。

2等以下は次のようになります。

2等 : 本数字5個と一致,ボーナス数字1個と一致
loto_base = math.factorial(43) // (math.factorial(43 - 6) * math.factorial(6))
print('{0}/{1}'.format(6, loto_base))
print('{0:.10f}%'.format(6/loto_base*100))
6/6096454
0.0000984179%

3等 : 6個のうち5個が本数字に一致
loto_base = math.factorial(43) // (math.factorial(43 - 6) * math.factorial(6))
loto3 = (math.factorial(6) // (math.factorial(6 - 5) * math.factorial(5)))*37-6
print('{0}/{1}'.format(loto3, loto_base))
print('{0:.10f}%'.format(loto3/loto_base*100))
216/6096454
0.0035430432%

4等 : 6個のうち4個が本数字に一致
loto_base = math.factorial(43) // (math.factorial(43 - 6) * math.factorial(6))
loto4 = (math.factorial(6) // (math.factorial(6 - 4) * math.factorial(4)))* \
((math.factorial(37) // (math.factorial(37 - 2) * math.factorial(2))))
print('{0}/{1}'.format(loto4, loto_base))
print('{0:.10f}%'.format(loto4/loto_base*100))
9990/6096454
0.1638657488%

5等 : 6個のうち3個が本数字に一致
loto_base = math.factorial(43) // (math.factorial(43 - 6) * math.factorial(6))
loto5 = (math.factorial(6) // (math.factorial(6 - 3) * math.factorial(3)))* \
((math.factorial(37) // (math.factorial(37 - 3) * math.factorial(3))))
print('{0}/{1}'.format(loto5, loto_base))
print('{0:.10f}%'.format(loto5/loto_base*100))
155400/6096454
2.5490227598%

さて
5等は1000円です。
2.5%の確率でしか当たらないので
40回買っても1000円しか戻ってこないのです。

1位がでなければキャリーオーバーで
持ち越しになり、金額が増えますが
そもそも600万分の1の確率では
人生において当たることは
ほぼないでしょうね。


今回のラストはポーカーです。

ポーカーはトランプ52枚を使ったゲームで
役が決まっています。

その役がどれだけ有るのかを求めます。

役は
一番強い役がロイヤルフラッシュ
(ロイヤルストレートフラッシュ)

ストレートフラッシュ: 連続した数字で(絵柄)
同じスートの5枚のカード。

ストレートフラッシュ同士の場合は、
最もランクが高いカードを持つプレイヤーが勝者
最も強いストレートフラッシュは同じスートのA-K-Q-J-10

フォーカード: 同じランクのカード4枚と他1枚カード
フォーカード同士の場合は、同じランクのカード
4 枚のランクが最も高いプレイヤーが勝者

フルハウス: 同じランクのカード 3 枚と別の同じランクのカード 2 枚。
(スリーカードとワンペアの組み合わせ)
フルハウス同士の場合は、3 枚 1 組のカードのランクが最も高いプレイヤーが勝者

フラッシュ: 同じスートの 5 枚のカード。
フラッシュ同士の場合は、最もランクが高いカードを持つプレイヤーが勝者

ストレート: 連続した数字の 5 枚のカード。
ストレート同士の場合は、最もランクが高いカードを持つプレイヤーが勝者
最も強いストレートは A-K-Q-J-T (エースハイ)、最も弱いストレートは 5-4-3-2-A (ファイブハイ)

スリーカード: 同じランクのカード 3 枚と、ランクの異なる 2 枚のサイドカード。
スリーカード同士の場合は、3 枚 1 組のカードのランクが最も高いプレイヤーが勝者

ツーペア: 同じランクのカード 2 枚 1 組が 2 組と、1 枚のサイドカード。
ツーペア同士の場合は、最もランクが高いペアを持つプレイヤーが勝者

ワンペア: 同じランクのカード 2 枚と、ランクの異なる 3 枚のサイドカード。
ワンペア同士の場合は、最もランクが高いペアを持つプレイヤーが勝者

ハイカード: 上記のどれにも当てはまらない手札。
ブタとも言います。

今回は役を判定するプログラムを作って
全カードの組み合わせからその役がなんなのかを判定して
役の組み合わせ数を求めます。

デッキはカード52枚として
それを判定する関数を作成し
全52枚の中から5枚を選んだ際の組み合わせから
役が何かを求めて役の個数をカウントします。
# デッキの生成
deck=[b+':'+str(a) for a in range(1,14) for b in ['C','S','D','H']]
# 役の判定
def jadge_role(card):
    s = {}
    for c in card:
        k = int(c.split(':')[1])
        if k in s:
            s[k]+=1
        else:
            s[k] =1
    t = {c.split(':')[0] for c in card}
    n = sorted([c for c in s.keys()])
    if len(t)==1 and all([1 in n,10 in n ,11 in n,12 in n,13 in n]):
        return 'RSF'
    if len(t)==1 and (all([1 in n,10 in n ,11 in n,12 in n,13 in n]) or
             (max(n)-min(n)==4) and len(s)==5):
        return 'SF'
    if 4 in s.values():
        return '4C'
    if 3 in s.values() and 2 in s.values():
        return 'FH'
    if len(t)==1:
        return 'FL'
    if (all([1 in n,10 in n ,11 in n,12 in n,13 in n]) or
             (max(n)-min(n)==4) and len(s)==5):
        return 'ST'
    if 3 in s.values():
        return '3C'
    if list(s.values()).count(2)==2:
        return '2P'
    if list(s.values()).count(2)==1:
        return '1P'
    return 'BT'
# 組み合わせを計算
cards = itertools.combinations(deck,5)
calc_dict = {}
for card in cards:
    role = jadge_role(card)
    if role in calc_dict:
        calc_dict[role] += 1
    else:
        calc_dict[role]   = 1

# 結果
poker_base = math.factorial(52) // (math.factorial(52 - 5) * math.factorial(5))
print(poker_base)
for k,v in sorted(calc_dict.items(),reverse=True,key=lambda x:x[1]):
    print(k,'\t',v,'\t','{0:.10f}%'.format(v/poker_base*100))
2598960

BT  1302540 50.1177394035%
1P  1098240 42.2569027611%
2P    123552 4.7539015606%
3C      54912 2.1128451381%
ST      10200 0.3924646782%
FL         5108 0.1965401545%
FH        3744 0.1440576230%
4C          624 0.0240096038%
SF            36 0.0013851695%
RSF           4 0.0001539077%

このような結果になります。
ロイヤルストレートフラッシュは
約64万回に1回ほどは出る計算ですね

フラッシュとストレートでは
ストレートの方が2倍も出る確率が高いのです。
なのでどちらかを迷う場合は
確率の高いストレートを狙うというのが
戦略になるのかもしれませんね。


いろいろなギャンブルにまつわる
組み合わせと確率を求めてみました。

次は
戦略なども考えていきたいかなと思っております。

それでは