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

昨日までのはこちら

[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)

## 身近に有る確率

割と身近なところにある確率の問題をプログラミングで考えてみましょう。

### 30人クラスで同じ誕生日の生徒がいる確率は？

小中学校のクラスの人数は大体これくらいかと思いますが
30人クラスで同じ誕生日の人が1組みでもいる確率は
どれくらいになるでしょうか？

`1組みでも誕生日が一致している確率 = 1 - 全員の誕生日が異なる確率`

計算式だと

$1- \frac{365 \times 364 \times 363 \times ... (365-29)　}{365^{30}}$

になります。

面倒臭いのでPythonで解きましょう。

```python
from functools import reduce
from operator import mul

n = 30
a1 = [i for i in range(365,365-n,-1)]
a2 = [365 for i in range(n)]
print('{:%}'.format(1- reduce(mul, a1)/reduce(mul, a2)))
```
70.631624%

大体70%くらいですね。
30人集まれば70%の確率で1組みは同じ誕生日を祝うことになるでしょう。

**50人クラスまでの確率はどれくらいか？**

まとめて図示します。

```python
from functools import reduce
from operator import mul
import matplotlib.pyplot as plt
%matplotlib inline

plt.figure(figsize=(16,5))
x,y = [n for n in range(2,51)] , []
for n in x:
    a1 = [i for i in range(365,365-n,-1)]
    a2 = [365 for i in range(n)]
    y.append(1-reduce(mul, a1)/reduce(mul, a2))

plt.bar(x,y)
plt.grid()
plt.show()
```

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/b04fe70f-58d2-96af-733a-4bd63f2e2a15.png)

20人で40%
50人クラスで97%くらいは
同じ誕生日の人が居そうです。

会社であれば、100人とかいると思うので大体同じ誕生日の人がいる筈です。

## 当たる確率1%のガチャ、100回連続で外れる確率は確率は？

ガチャを引いた際に1%の確率で当たるとすると100回連続で外れる確率が
どれくらいになるでしょうか？

こんだけ引いてるんだから必ず当たるのでしょうか？！？！

`100連続で外れる確率 = 1回引いて外れる確率^(100)`

つまりは

$(\frac{99}{100})^{100}$ 

です。

割合を計算してみると

```python
print('{:%}'.format((99/100)**100))
```
36.603234%

結構な確率で外れると思いませんか？

本当に3倍祭りなのか！！！って思う時ありますよね。

**どれくらい引いたらどれくらいの確率で当たりそうか?**

`当たる確率 = 1-外れる確率`
になるので、何回引いたらどれくらい当たるのかを考えてみましょう。

```python
import matplotlib.pyplot as plt
%matplotlib inline

plt.figure(figsize=(16,5))
x,y = [n for n in range(1,501)],[]
for n in x:
    y.append(1-(99/100)**n)

plt.bar(x,y)
plt.grid()
plt.show()
```

![download-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/8d30da80-8aa3-6358-5ade-a9c62a13d2e0.png)

この場合100回引いた程度では、3割は外れます。
200回引いてようやくあたりが80%超えてきますね。

500回も引けば、外れることはほぼほぼないように見えます。
ただ確実に当たる事にはならないので、運が悪いと外れることもあるわけです。

本当に1%の確率で当たるかどうか?
シミュレーションしてみましょう。

1%の確率で当たるガチャを100回して何回目で当たったのか人数を数えます。

```python
import random
import matplotlib.pyplot as plt
%matplotlib inline

weights = [0.99,0.01]
d = {b:0 for b in range(101)}
for p in range(10000):
    a = 0
    for i in range(100):
        tf = random.choices([False,True], weights=weights)[0]
        if tf:
            a=i+1
            break
    d[a]+=1

plt.figure(figsize=(16,5))
x = list(d.keys())
y = list(d.values())
plt.bar(x,y)
plt.grid()
plt.show()
```

![download-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/8730d7f3-d4b2-0473-e91c-a56e9751d8dc.png)

0は外れた人の数、他は何回目に当たったかの人数です。

先ほどの確率では36%は外れた人が出るので1万人だと3600人ほどは外れる人が出る計算です。

1万人くらいにアンケートをとってもし、この外れた人の人数がもっと少なくなる場合は
ガチャの確率が操作されている可能性が見えてきますが
そもそも大量の人数にアンケートを取るのが大変ですね。

### 日本シリーズが最終戦までもつれる確率は?

野球のお話です。
日本シリーズは先に4回買った方が優勝で、全部で7回行われます。
セ、パ共に勝ち負けの確率を50%とするときに
第七戦までもつれ込む確率はどれくらいでしょうか？

確率を求めるには全ての組み合わせを考えれば良さそうですね。
4勝もしくは4負が出た時点で終わってしまうので
6戦までで勝負がついていない組み合わせは

```python
import itertools

p4 = [i for i in itertools.product(['勝','負'],repeat=4) if i.count('勝')==4 or i.count('負')==4]#4戦で終わり
p5 = [i for i in itertools.product(['勝','負'],repeat=5) if (i[0:4].count('勝')<4 and i[0:4].count('負')<4) and (i.count('勝')==4 or i.count('負')==4)]#5戦で終わり
p6 = [i for i in itertools.product(['勝','負'],repeat=6) if (i[0:5].count('勝')<4 and i[0:5].count('負')<4) and (i.count('勝')==4 or i.count('負')==4)]#6戦で終わり
p7 = [i for i in itertools.product(['勝','負'],repeat=6) if i[0:6].count('勝')<4 and i[0:6].count('負')<4]#6戦で終わらない

print('4戦で終わり' , len(p4))
for a in p4:
    print(' '.join(a))
print('5戦で終わり' , len(p5))
for a in p5:
    print(' '.join(a))
print('6戦で終わり' , len(p6))
for a in p6:
    print(' '.join(a))
print('6戦で終わらない' , len(p7))
for a in p7:
    print(' '.join(a))
```
4戦で終わり 2
勝 勝 勝 勝
負 負 負 負

5戦で終わり 8
勝 勝 勝 負 勝
勝 勝 負 勝 勝
勝 負 勝 勝 勝
勝 負 負 負 負
負 勝 勝 勝 勝
負 勝 負 負 負
負 負 勝 負 負
負 負 負 勝 負

6戦で終わり 20
勝 勝 勝 負 負 勝
勝 勝 負 勝 負 勝
勝 勝 負 負 勝 勝
勝 勝 負 負 負 負
勝 負 勝 勝 負 勝
勝 負 勝 負 勝 勝
勝 負 勝 負 負 負
勝 負 負 勝 勝 勝
勝 負 負 勝 負 負
勝 負 負 負 勝 負
負 勝 勝 勝 負 勝
負 勝 勝 負 勝 勝
負 勝 勝 負 負 負
負 勝 負 勝 勝 勝
負 勝 負 勝 負 負
負 勝 負 負 勝 負
負 負 勝 勝 勝 勝
負 負 勝 勝 負 負
負 負 勝 負 勝 負
負 負 負 勝 勝 負

6戦で終わらない 20
勝 勝 勝 負 負 負
勝 勝 負 勝 負 負
勝 勝 負 負 勝 負
勝 勝 負 負 負 勝
勝 負 勝 勝 負 負
勝 負 勝 負 勝 負
勝 負 勝 負 負 勝
勝 負 負 勝 勝 負
勝 負 負 勝 負 勝
勝 負 負 負 勝 勝
負 勝 勝 勝 負 負
負 勝 勝 負 勝 負
負 勝 勝 負 負 勝
負 勝 負 勝 勝 負
負 勝 負 勝 負 勝
負 勝 負 負 勝 勝
負 負 勝 勝 勝 負
負 負 勝 勝 負 勝
負 負 勝 負 勝 勝
負 負 負 勝 勝 勝


`６戦で終わらない組み合わせ / 6戦までの組み合わせ`
組み合わせで考えると`20/(2 + 8 + 20 + 20)`で0.4 = 40%となりますね。

７試合で勝負がつく組み合わせを考えるとこの6戦までで終わらない組み合わせ
20の倍の40通りあります。

勝ち負けの確率は2分の1と考えると
`40通り × (1/2)^7 ＝ 5/16 = 31.25%`

確率で考えると`31.25%`は第七戦まで行くようです。

何れにせよ3割は第七戦までもつれる訳です。


## まとめ

色々な確率の問題を考えながらプログラムに落とし込んでいくと
プログラミングが上達すると思います。

色んな問題を解いてみましょう。

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

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

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

Twitter：
https://twitter.com/otupython