乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

シミュレーション

今回はビンゴ5を買い続けてみることにしました

さて結果はどうなってしまうのでしょうか?!?!

解説動画はこちら



さて今回はビンゴ5についてです。

ビンゴ5は1994年10月1日に発売が開始された
数字選択式全国自治宝くじの一つで

タテ・ヨコ3マスずつ、計9個のマス目のうち
中央のFREEのマスを除いた8個のマス目に
記載された5つの数字の中から1つずつ
01から40までの数字のうち
計8個の数字を選択するものです。

1口200円で購入可能ですね。

選択箇所が8つあるので
それぞれ選べる数字は次のようになっています

[01, 02, 03, 04, 05] [06, 07, 08, 09, 10] [11, 12, 13, 14, 15]
[16, 17, 18, 19, 20]         フリー      [21, 22, 23, 24, 25]
[26, 27, 28, 29, 30] [31, 32, 33, 34, 35] [36, 37, 38, 39, 40]


真ん中はフリーなので選べないですね

ビンゴは縦横斜めの数字があえば
ラインが一つ揃います。

最大ライン数は8つ
ライン数によって当選金額も変わります。

数字の組み合わせは 5 ** 8 == 390625通り
賞金は次のようになっています

スクリーンショット 2021-05-15 16.39.53

さて
ここからシミュレーションすることを考えましょう。

まず最初はビンゴ5の当たり目を作る所からです
import random

def bingo5hits():
    # 8か所の数字の組み合わせ
    base = [[i2 for i2 in range(i1*5+1,i1*5+6)] for i1 in range(8) ]

    # ランダムに1つ選ぶ
    bingo5 = [random.choice(b) for b in base]
    
    return bingo5

print(bingo5hits())
[1, 7, 12, 16, 23, 28, 32, 38]

これを当たりとして
自分の選択数字と比べてみて
当たりをチェックしましょう

当たり目からラインの成立をチェックする
def check_bingo(b , s):
    lines = 0
    # 縦1のライン
    if b[0]==s[0] and b[3]==s[3] and b[5]==s[5]:
        lines+=1
    # 縦2のライン
    if b[1]==s[1] and b[6]==s[6]:
        lines+=1
    # 縦2のライン
    if b[2]==s[2] and b[4]==s[4] and b[7]==s[7]:
        lines+=1
    # 横1のライン
    if b[0]==s[0] and b[1]==s[1] and b[2]==s[2]:
        lines+=1
    # 横2のライン
    if b[3]==s[3] and b[4]==s[4]:
        lines+=1
    # 横2のライン
    if b[5]==s[5] and b[6]==s[6] and b[7]==s[7]:
        lines+=1
    # 斜め1のライン
    if b[0]==s[0] and b[7]==s[7]:
        lines+=1
    # 斜め2のライン
    if b[2]==s[2] and b[5]==s[5]:
        lines+=1
    return lines

次はライン数から賞金額を計算してみましょう。
def pay_off(a):
    if a==1:
        return 200
    if a==2:
        return 700
    if a==3:
        return 2500
    if a==4:
        return 18200    
    if a==5:
        return 45000
    if a==6:
        return 300000    
    if a==8:
        return 5556200
    return 0

これで獲得賞金も問題ないですね

出目のチェックはこんな感じで出来ます。

出目の表示
def print_num(n):
    for i,b in enumerate(n,start=1):
        print(b,end='\t')
        if i==4:
            print(' - ',end='\t')
        if i==3 or i==5:
            print()
            
num = [i*5+1 for i in range(8)]
print_num(num)

ここからはシミュレーション実行です
早速100枚買った結果を実施してみましょう。

100枚買ってみる
import itertools

pay,p_off,count,result = 0,0,0,[]

# 選択数字の組み合わせ
b = [[i2 for i2 in range(i1*5+1,i1*5+6)] for i1 in range(8) ]

# 出目の組み合わせ
p = list(itertools.product(b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]))

# 当たりはコレ
bingo5 = bingo5hits()

# 100枚の選択
selects = random.choices(p, k=100)

# 当たりの判定
for select in selects:
    # ライン数
    line = check_bingo(bingo5 , select)
    # 獲得金額
    p_off += pay_off(line)
    # 結果
    result.append(line)
    pay+=200
    
calc ={k:0 for k in range(9) if k!=7}
for row in result:
    if row in calc:
        calc[row] +=1
    
# 最終結果
print('総支払額 : {0}円'.format(pay))
print('獲得金額 : {0}円'.format(p_off))
print('当たりの数 : {0}回'.format(len([r for r in result if r>0])))
for k,v in sorted(calc.items()):
    print('ライン : {0} , {1:02}回'.format(k,v))
総支払額 : 20000円
獲得金額 : 4300円
当たりの数 : 19回
ライン : 0 , 81回
ライン : 1 , 18回
ライン : 2 , 01回
ライン : 3 , 00回
ライン : 4 , 00回
ライン : 5 , 00回
ライン : 6 , 00回
ライン : 8 , 00回

当たり目等はランダムとしています。
全然当たりませんねwwwwwwwwwwww

くやしいので100枚買うを500回行ってみましょう
import itertools

calc ={k:0 for k in range(9) if k!=7}
pay,p_off,count,all_result = 0,0,0,[]
for i in range(500):
    result = []
    b = [[i2 for i2 in range(i1*5+1,i1*5+6)] for i1 in range(8) ]
    p = list(itertools.product(b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]))
    bingo5 = bingo5hits()
    selects = random.choices(p, k=100)
    for select in selects:
        line = check_bingo(bingo5 , select)
        p_off += pay_off(line)
        result.append(line)
        pay+=200
    all_result.append(result)
    for row in result:
        if row in calc:
            calc[row] +=1
    
# 最終結果
print('総支払額 : {0:08}円'.format(pay))
print('獲得金額 : {0:08}円'.format(p_off))
for k,v in sorted(calc.items()):
    print('ライン : {0} , {1:02}回'.format(k,v))
総支払額 : 10000000円
獲得金額 : 03631800円
ライン : 0 , 41736回
ライン : 1 , 7283回
ライン : 2 , 812回
ライン : 3 , 138回
ライン : 4 , 24回
ライン : 5 , 05回
ライン : 6 , 02回
ライン : 8 , 00回

1000万円分買ってみましたが
360万円しか返ってきませんでした

最終的に投資金額の何%
回収できるのかというと?
print(p_off/pay)
0.36318

4割程度ですね

ビンゴ5では確率的に
支払った金額の4割程度に落ち着くようです!

かければかけるほど、損をするみたいなので
貧乏5って名前に変えたらどうでしょうか!!!!!

1等は40万分の1に近い確率なので
8000万円分くらい買わないと
当たらなさそうですねーー

いやー宝くじは
変えば買うほど損をする!!!!!

格言が出たところで
終わりにしたいと思います

それでは。


ガチャなどの身近に有る確率の問題を解いてみました。


解説動画はこちら



初めに簡単な問題を

問1. 30人クラスで同じ誕生日の生徒がいる確率は?

考えたい方はここでスクロールを止めて
考えてみてください。








答え:

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

となるので

計算式は
スクリーンショット 2020-05-24 15.50.12


こんな感じになります。

計算めんどくさいので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%

出ました。

30人クラスだと7割くらいの確率で
1組みくらいは同じ誕生日の人が居そうですね。

50人までの確率を調べてみましょう。
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

20人クラスでも40%ほど
50人クラスでは97%にもなります。

だいたい会社だと100人超えてくると思うので
1組みは同じ誕生日の人がいるんじゃないかと思います。

問2. 当たる確率1%のガチャ
100回連続で外れる確率は確率は?

ガチャの確率の問題です。

自分もよくガチャ引きますが
3倍祭りとか言ってるのに
全然当たらないですよねーーーー






答えは

100連続で外れる確率
1回引いて外れる確率の(100乗)

 と言うことで
計算は簡単です。

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

ガチャ確率1%だと
100回引いても3割以上は1回も当たらないんです!!

では
どれくらい引いたら当たるかを
シミュレーションしてみましょう。

当たる確率は 1-外れる確率 で計算できますね。

500回引いた際の当たる確率のシミュレーションです。
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

100回引いた程度だと36%も外れるわけですから
もっと引かないと当たらないですよね。

500回ほど引けばほぼ当たりそうな感じはしますが
確実ではないと言うところがミソです。

本当に1%の確率で当たるのか??
確率はちゃんと1%なのか??

と言う疑問を解消するには
1万人ほどアンケートとってみるしか
ないんじゃないかと思います。

1%の確率で当たるガチャを100回引く
1万人ガチャシミュレーションの結果は・・・

import random

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
import matplotlib.pyplot as plt
%matplotlib inline

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

plt.bar(x,y)
plt.grid()
plt.show()
download-2

0は外れた人の数、それ以外は当たった回数で何人いるかです。

0のところは先ほどの確率で行くと36%=3600人ほど
外れているのが分かります。

1万人くらいのアンケートをとって
外れてる人が何人いるのかを調べれば
本当にガチャの確率が1%だったのかを
検証できるかもしれませんね。


今回はここまでです。
それでは。


このページのトップヘ