100日後にエンジニアになるキミ - 64日目 - プログラミング - 確率について2

昨日までのはこちら

[100日後にエンジニアになるキミ - 63日目 - プログラミング - 確率について1](https://qiita.com/otupy/items/0196897ae4d2134794fa)

[100日後にエンジニアになるキミ - 59日目 - プログラミング - アルゴリズムについて](https://qiita.com/otupy/items/f1a5e81633b868f3b5ed)

[100日後にエンジニアになるキミ - 53日目 - Git - Gitについて](https://qiita.com/otupy/items/0abaad82a7f3fea73f1f)

[100日後にエンジニアになるキミ - 42日目 - クラウド - クラウドサービスについて](https://qiita.com/otupy/items/d1765f1541a104ed6133)

[100日後にエンジニアになるキミ - 36日目 - データベース - データベースについて](https://qiita.com/otupy/items/7af17635d576677606dc)

[100日後にエンジニアになるキミ - 24日目 - Python - Python言語の基礎1](https://qiita.com/otupy/items/6d1e5453f530e07b7aec)

[100日後にエンジニアになるキミ - 18日目 - Javascript - JavaScriptの基礎1](https://qiita.com/otupy/items/2f71d5f9c754b29d9555)

[100日後にエンジニアになるキミ - 14日目 - CSS - CSSの基礎1](https://qiita.com/otupy/items/61a97863f6df14171994)

[100日後にエンジニアになるキミ - 6日目 - HTML - HTMLの基礎1](https://qiita.com/otupy/items/cd2315dcb38671cfded0)

## 期待値について

`期待値`とは1回の試行で得られる平均値のことです。

得られる全ての値とそれが起こる確率の積を足し上げたものです。

サイコロの例で考えてみましょう。

サイコロの目が出る確率は以下の通りです。

| 出る目(x) | 1 | 2 | 3 | 4 | 5 | 6 |
|:--|:--|:--|:--|:--|:--|:--|
| 確率(p) | 1/6 | 1/6 | 1/6 | 1/6 | 1/6 | 1/6 |

出る目の期待値は`出る目 * 確率`を足し上げたものです。

$ 1 * \frac{1}{6} + 2 * \frac{1}{6} +3 * \frac{1}{6} +4 * \frac{1}{6} +5 * \frac{1}{6} +6 * \frac{1}{6} = 3.5$

サイコロを１回振る際の平均は3.5になると期待できます。

## 還元率

ギャンブルにも期待値があります。その際掛け金に対して、払い戻される金額の割合を
`還元率`と言っていたりします。

例えば1000万円払って50%の確率で1500万円、40%で500万円、10%の確率で0円になるギャンブルがあったとします。

`期待値`は`（50%×１５00万円）＋（4０%×500万円）＋（2０%×0円）＝950万円`

`還元率`は`950万円/１000万円`で`95%`となります。

こんなギャンブルがあったらやりますか？
やり続ければやり続けるほど、お金が減っていくと思います。

よく言われている国内のギャンブルの還元率は

| 種類 | 還元率 |
|:--:|:--:|
| 競馬 | 約７５％ |
| 競輪 | 約７５％ |
| 競艇 | 約７５％ |
| オートレース | 約７５％ |
| 宝くじ | 約４６% |
| サッカーくじ | 約５０% |
| パチンコ | 約８０～９０% |

やればやるほどお金が減っていくわけですね。

宣伝費をかけて集客をしても
人が集まれば集まるだけ親が儲かるのですから
たまらない商売ですね。

基本的に還元率が100%を超えるギャンブルは存在し得ないハズです。

もし還元率が100%を超えるギャンブルが有ったとしたら
掛けている側のお金がどんどん増えていきます。

## ギャンブルの確率

様々なギャンブルの確率を考えてみましょう。

### 競馬

競馬は16,18頭だてで着順を当てにいくものです。
当てる着順によって買い方が変わります。

**単勝**

1着を当てに行きます。

この場合当たる確率は
16頭だて$\frac{1}{16} = 6.25$%
18頭だて$\frac{1}{18} = 5.556$%

**複勝**

1-3着に入る馬を当てます。

予想した馬が1位でも3位でも良いので
単純に単勝の3倍になります。

この場合当たる確率は
16頭だて$\frac{3}{16} = 18.75$%
18頭だて$\frac{3}{18} = 16.667$%

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

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

**枠連**

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

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

36通り有るので
$\frac{1}{36} = 2.7778$%

**馬連**

選んだ2頭が1-2着になる組み合わせで1-2,2-1どちらでも良いという買い方です。

16頭だて$\frac{1}{120} = 0.83333$%
18頭だて$\frac{1}{153} = 0.65359$%

**馬単**

選んだ2頭が1-2着になる組み合わせで1-2着をそのまま当てる買い方です。

16頭だて$\frac{1}{240} = 0.41667$%
18頭だて$\frac{1}{306} = 0.3268$%

**ワイド**

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

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

16頭だて$\frac{3}{120} = 2.5$%
18頭だて$\frac{3}{153} = 1.9608$%

**3連複**

1着・2着・3着になる組み合わせを順不同で予想する
組み合わせ`16C3` , `18C3`

16頭だて$\frac{1}{560} = 0.17857$%
18頭だて$\frac{1}{816} = 0.12255$%

**3連単**

1着・2着・3着になる組み合わせを着順通りに予想する
順列`16P3`, `18P3`

16頭だて$\frac{1}{3360} = 0.029762 $%
18頭だて$\frac{1}{4896} = 0.020425 $%

**WIN5**

JRAが指定する５つのレース
それぞれの1着を予想するものです。
単勝の5乗ですね

18頭だて$\frac{1}{1889568} = 0.0000529221$%

約190万分の1の確率です。

宝くじなどの確率が`1000万分の1`の確率で同じくらいの金額なので
WIN5の方が`期待値`は上かと思います。

競馬の確率の高さは

複勝＞単勝＞枠連＞ワイド＞馬連＞馬単＞３連複＞３連単＞WIN5

になります。


### ロトシックス

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

**1等**

本数字6個すべて一致 `43C6`

$\frac{1}{6096454} = 0.0000164030$%

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

**2等**

本数字５個と一致,ボーナス数字１個と一致

$\frac{6}{6096454} = 0.0000984179$%

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

**3等**

６個のうち５個が本数字に一致

$\frac{216}{6096454} = 0.0035430432$%

大雑把に3万分の1くらいの確率です。


**4等**

６個のうち４個が本数字に一致

$\frac{9990}{6096454} = 0.1638657488 $%

600回に一回くらいは当たる確率ですかね。

**5等**

６個のうち３個が本数字に一致

$\frac{155400}{6096454} = 2.5490227598 $%

40回に1回くらいの確率ですね。

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

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

**ポーカー**

ポーカーはトランプ52枚を使ったゲームで役が決まっています。
その役がどれだけ有るのかを求めます。

役は

| 役 | 内容 |
|:--|:--|
| ロイヤルストレートフラッシュ | A-K-Q-J-10 |
| ストレートフラッシュ | 連続した数字で(絵柄)<br/>同じスートの5枚のカード |
| フォーカード | 同じランクのカード4枚と他1枚カー |
| フルハウス | 同じランクのカード 3 枚と別の同じランクのカード 2 枚。 |
| フラッシュ | 同じスートの 5 枚のカード。 |
| ストレート | 連続した数字の 5 枚のカード。 |
| スリーカード | 同じランクのカード 3 枚と、ランクの異なる 2 枚のサイドカード。 |
| ツーペア | 同じランクのカード 2 枚 1 組が 2 組と、1 枚のサイドカード。 |
| ワンペア | 同じランクのカード 2 枚と、ランクの異なる 3 枚のサイドカード。 |
| ハイカード | 上記のどれにも当てはまらない手札。ブタ |

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

デッキはカード52枚としてそれを判定する関数を作成し
全52枚の中から5枚を選んだ際の組み合わせから
役が何かを求めて役の個数をカウントします。

```python
# デッキの生成
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.12% |
| 1P | 1098240 | 42.26% |
| 2P | 123552 | 4.75% |
| 3C | 54912 | 2.1128% |
| ST | 10200 | 0.39246% |
| FL | 5108 | 0.19654% |
| FH | 3744 | 0.144057% |
| 4C | 624 | 0.024009% |
| SF | 36 | 0.001385% |
| RSF | 4 | 0.0001539% |

このような結果になります。

ロイヤルストレートフラッシュは`約64万回に1回`ほどは出る計算ですね

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



## まとめ

確率、期待値が求められれば、還元率についても計算することができます。
ガチャなどはルーレットゲームなどと一緒なので
確率を求めれば、どれくらいの金額を突っ込めばキャラが当たるのか
シミュレーションできます。

ゲームやガチャなどでは確率、期待値を求めることも多いので
様々な確率の計算方法などを押さえておくといいかもしれません。


君がエンジニアになるまであと36日

## 作者の情報
乙pyのHP：
http://www.otupy.net/

Youtube：
https://www.youtube.com/channel/UCaT7xpeq8n1G_HcJKKSOXMw

Twitter：
https://twitter.com/otupython