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

確率

今回は昔懐かしい
カイジの沼のシミュレーションです。

解説動画はこちら




カイジの沼のシミュレーション

沼とは

漫画『賭博破戒録カイジ』に登場する架空のパチンコ台

帝愛グループの運営するカジノに設置されている
パチンコの中でも特別な台で玉が1発あたり4000円
挑戦は最低300万円からという設定

その一方で、今までの挑戦者が消費した玉が
全てプールされる仕組みになっており
運良く大当たりを引ければ総取りで莫大な額の金を手にできるとか


仕掛け・役物

ここからは確率を計算するための
沼のギミックについてです。

1.釘の森

釘が密集した配置になっている「釘の森」
通常時の設定Cは1/100程度

2.スル

開閉する羽根のある電動役物「スルー」
釘の森を突破した玉を更にふるい落とす
確率は不明なので
ここでは通過率を1/5としておきます

3.3段クルーン

沼の本丸である「三段クルーン」
円形の皿に穴が3つ/4つ/5つ空いていて
当たりの穴に入ると次の段に進める

数学的にはクルーンに入ってさえしまえば
約1/60の確立で当たる


というような設定にはなっていますが
漫画の設定上ではこの台にはイカサマがあり
この確率では入らないようにはなっています。

しかし、今回は考慮しないで
イカサマなしだとどうなるかを見ていきたいと思います。



沼のシミュレーションコード


簡易な確率計算で大当たりしたかどうかだけ返す関数を用いて
シミュレーションしていきます。
最大回数は10万回(4億円相当)とします。

import numpy as np
import random
import pandas as pd
import matplotlib.pyplot as plt

# 確率でヒットするかどうかを判定する
def is_hit(n: int) -> bool:
    return random.randint(1, n) == 1

def numa_charenge():
  # 釘の森の通過
  mori = is_hit(100)
  if not mori:
    return False

  # スルーの通過
  throw = is_hit(5)
  if not throw:
    return False

  # クルーン1段目通過
  first = is_hit(3)
  if not first:
    return False

  # クルーン2段目通過
  second = is_hit(4)
  if not second:
    return False

  # クルーン3段目通過
  third = is_hit(5)
  if not third:
    return False
  else:
    return True


# 1000回施行して測ってみる
ball_price = 4000 # パチンコ玉の価格

def numa_result(num):
  all_result = []
  for a in range(1000):
    cumulative = 0
    for i in range(num):
      cumulative += ball_price
      is_atari = numa_charenge()
      if is_atari:
        all_result.append([i+1, cumulative,1])
        break
      if i == num-1:
        all_result.append([i+1, cumulative,0])
  return all_result

num = 100000 # 1回あたりの最大施行回数
all_result = numa_result(num)

df = pd.DataFrame(all_result,columns=["balls","cumulative","hit"])
df.head()
balls cumulative hit
0 30959 123836000 1
1 29604 118416000 1
...

plt.figure(figsize=(12, 6))
df["cumulative"].hist(bins=20)
plt.show()
download

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


どれくらい注ぎ込めば当たるのか?


シミュレーション結果は使った額の累計を入れているので
それを用いれば、その金額以下の回数と
全体の回数から大体の確率を求められます。
times_300 = len(df[df["cumulative"]<3000000])
print(f"300万円で大当たりになる可能性 : {times_300/1000*100} % ")

なおこのシミュレーションの結果は
幾何分布に近似するため以下のようなコードで
回数あたりの大当たり確率の理論値が出せます。
# 幾何分布上の理論値
for i in range(10):
  p = 1 / 30000
  n = (i+1) * 10000
  prob = 1 - (1 - p)**n
  print(f"{i+1:02}万回で当たる確率 : {prob:.6f}")
01万回で当たる確率 : 0.283473
02万回で当たる確率 : 0.486589
03万回で当たる確率 : 0.632127
04万回で当たる確率 : 0.736409
05万回で当たる確率 : 0.811130
06万回で当たる確率 : 0.864669
07万回で当たる確率 : 0.903032
08万回で当たる確率 : 0.930520
09万回で当たる確率 : 0.950215
10万回で当たる確率 : 0.964328


シミュレーション結果もこの理論値に
近似してますね。


まとめ


沼の設定が玉が1発あたり4000円
3万発に1回の確率(100x5x3x4x5)
で当たるのだとしたら3億注ぎ込めば
9割くらいは大当たりするのではないか?

あくまでイカサマが無い事が前提ですが.....
イカサマさえなければ無尽蔵にお金を注ぎ込めるなら
勝てる気がしなくもない今日この頃でした。

それでは

今回は直感に反する確率の逆説の問題集です


解説動画はこちら



直感に反する確率の問題

なんとなくコレかなと思ったけど
答えはそれと違っていたというような
直感に反する答えが出そうな問題です。


問題とともに
回答に使用したコードを載せておきます。



1.確率の逆説


第1問

サイコロを2回振るとき 少なくとも1回は1が出る確率は
1. 3分の1より小さい
2. ちょうど3分の1(33.3%)
3. 3分の1より大きい

# サイコロを2回振るとき 少なくとも1回は1が出る確率
import random

num = 1000000
count = 0
for _ in range(num):
    dices = [random.choice([1,2,3,4,5,6]),random.choice([1,2,3,4,5,6])]
    if 1 in dices:
        count+=1

print(f"少なくとも1が1回はでた回数 : {count}")
print(f"{count * 100 / num}%")



第2問

学校のクラス30人の生徒の中に誕生日が同じ人がいる確率は
1. 約30%
2. 約50%
3. 約70%
4. 約90%


# n人の生徒の中に誕生日が同じ人がいる確率
import random
from collections import Counter

birthdays = list(range(365))
num = 30
cnt, all_cnt = 0,0
for i in range(1000000):
    all_cnt+=1
    tmp = random.choices(birthdays,k=num)
    c = Counter(tmp)
    mx = c.most_common(1)
    if mx[0][1]>1:
        cnt+=1
print(f"誕生日が同じ人がいた回数 : {cnt}")
print(f"誕生日が同じ人がいる確率 : {cnt * 100 /all_cnt}%")




2.ギャンブラーの誤謬

過去の結果が現在の結果に影響すると誤って考える心理


第3問

コインを4回投げてすべて表が出た場合、次の投げで裏が出る確率は
1. 50%より小さい
2. ちょうど50%
3. 50%より大きい


# コインを投げて4回表が出た後の出目の確率
import random

def simulate_coin_tosses(trials):
    result = {'表':0,'裏':0}
    coins = [random.choice(['表', '裏']) for _ in range(trials)]
    for i in range(0, trials-5):
        if coins[i:i+4] == ['表', '表', '表', '表']:
            next = coins[i+4]
            result[next]+=1
    return result['表'], result['裏']

# 試行回数
k = 1000000
total_heads, total_tails = simulate_coin_tosses(k)

print(f"試行回数: {k}")
print(f"表の合計回数: {total_heads}")
print(f"裏の合計回数: {total_tails}")
print(f"4回表が出た後の裏が出る確率は : {total_tails * 100 / (total_heads + total_tails):.6}%")




第4問

コインを1000回投げた時に、連続して表が出る最高回数は
1. 8回より少ない
2. 8-10回くらい
3. 10回より多い


# コインをnum回投げて、連続して表が出る最高回数
import random

def max_consecutive_heads(trials):
    coins = [random.choice(['表', '裏']) for _ in range(trials)]
    #print(coins)
    #print(f"表の数 : {coins.count('表')}")
    max_count, current_count = 0, 0
    for coin in coins:
        if coin == '表':
            current_count += 1
            max_count = max(max_count, current_count)
        else:
            current_count = 0
    return max_count

# 試行回数
num = 1000
max_heads = [max_consecutive_heads(num) for _ in range(1000)]
mean_heads = sum(max_heads) / len(max_heads)
print(f"試行回数: {num}")
print(f"連続して出現した表の最高回数: {mean_heads}")



答えは
シミュレーションプログラムを実行するか
動画をご覧ください。




そんなに確率高くないだろうと思っていたら
意外と高い確率だったり
意外と低かったり

そんなこともあるんじゃないかと思います。

プログラムを使えば
色々シミュレーションして
おおよその確率を求めることができるので

さまざまな事象の確率を求めたいなら
プログラミングを習得するのが
おすすめです。


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

 

今回は最近流行りのポーカー
に関する確率のシミュレーションです

解説動画はこちら


 

ポーカーについて

ポーカーはトランプ5枚の手札の組み合わせで
役を作るゲームです。

1.ハイカード(強いカードの所持 2 < A)
2.ワンペア(同じ数字の組み合わせが1つ)
3.ツーペア(同じ数字の組み合わせが2つ)
4.スリーカード(同じ数字3つ)
5.ストレート(2,3,4,5,6 などの数字の並び)
6.フラッシュ(同じスートの組み合わせ HDCS)
7.フルハウス(スリーカードに加えて、同じ数字の組み合わせが1つ)
8.フォーカード(同じ数字4つ)
9.ストレートフラッシュ(ストレート + フラッシュ)
10.ロイヤルフラッシュ(AKQJTのフラッシュ)


テキサスホールデムルール


ポーカーのルールの一つで
プレイヤーそれぞれに配られた2枚のカードと
プレイヤー全員が共有する公開された
コミュニティカード"枚の計7枚で役を作り
チップをベットするなどの駆け引きを行うゲームルールです
(ベット周りの詳細なルールは割愛)


ここからはテキサスホールデムの
初期手札による勝率がどうなるのかを
検証するシミュレーションプログラムについてです。




役を計算するプログラム

シミュレーションを行うには
ポーカーの役の判定を行うプログラムが必要ですね

import random
from collections import Counter
from itertools import combinations

# ポーカーの役
POKER_HANDS = {
    0: "ハイカード",
    1: "ワンペア",
    2: "ツーペア",
    3: "スリーカード",
    4: "ストレート",
    5: "フラッシュ",
    6: "フルハウス",
    7: "フォーカード",
    8: "ストレートフラッシュ",
    9: "ロイヤルストレートフラッシュ"
}

# カードのランクとスート(HA=ハートのエース, D2=ダイヤの2)
RANKS = "23456789TJQKA"
SUITS = "HDSC"  # ハート, ダイヤ, スペード, クラブ
DECK = [s + r for r in RANKS for s in SUITS]

# 役の評価(スコアをタプルで返す)
def evaluate_hand(hand):
    ranks = sorted([RANKS.index(c[1]) for c in hand], reverse=True)
    suits = [c[0] for c in hand]
    rank_counts = Counter(ranks)
    flush = len(set(suits)) == 1
    straight = len(rank_counts) == 5 and (max(ranks) - min(ranks) == 4 or set(ranks) == {12, 3, 2, 1, 0})  # A-2-3-4-5対応

    # 役の判定(同率はRankで比較)
    if straight and flush:
        if set(ranks) == {12, 11, 10, 9, 8}:  # A, K, Q, J, 10
            return (9, max(ranks))  # ロイヤルストレートフラッシュ
        return (8, max(ranks)) # ストレートフラッシュ
    if 4 in rank_counts.values():
        return (7, max(k for k, v in rank_counts.items() if v == 4))  # フォーカード
    if 3 in rank_counts.values() and 2 in rank_counts.values():
        return (6, max(k for k, v in rank_counts.items() if v == 3))  # フルハウス
    if flush:
        return (5, ranks)  # フラッシュ
    if straight:
        return (4, max(ranks))  # ストレート
    if 3 in rank_counts.values():
        return (3, max(k for k, v in rank_counts.items() if v == 3))  # スリーカード
    if list(rank_counts.values()).count(2) == 2:
        return (2, sorted([k for k, v in rank_counts.items() if v == 2], reverse=True))  # ツーペア
    if 2 in rank_counts.values():
        return (1, max(k for k, v in rank_counts.items() if v == 2))  # ワンペア
    return (0, ranks)  # ハイカード

これを用いてシミュレーションを行なっていきます。



テキサスホールデムのシミュレーション

初期手札2枚と公開札5枚で、役を作り、勝率がどうなるか
4人で対戦をする際の勝率を出す
シミュレーションプログラムです。

user_num のところが対戦人数になるので
変更すれば、その人数での確率を求めることができます。
# モンテカルロ法で勝率計算
def monte_carlo_win_rate(my_hand, num_simulations=10000):
    wins = 0
    user_num = 3
    for _ in range(num_simulations):
        deck = DECK.copy()
        for card in my_hand:
            deck.remove(card)

        # 4人分の手札をランダムに配る
        random.shuffle(deck)
        opponent_hands = [deck[i * 2: (i + 1) * 2] for i in range(user_num)]
        community_cards = deck[6:11]

        # 各プレイヤーのベストハンドを評価
        my_best = max(evaluate_hand(list(comb)) for comb in combinations(my_hand + community_cards, 5))
        opponent_best = [max(evaluate_hand(list(comb)) for comb in combinations(hand + community_cards, 5)) for hand in opponent_hands]

        # 自分が最も強い手を持っているか判定
        if my_best > max(opponent_best):
            wins += 1

    return wins / num_simulations

# 例: 自分の手札をセットして勝率を計算
my_hand = ["HA", "HK"]  # ハートのエース・キング
win_rate = monte_carlo_win_rate(my_hand, num_simulations=5000)
print(f"勝率: {win_rate:.2%}")
勝率: 33.02%

カードの組み合わせを変えれば
その都度計算が行えます。



初期カードの組み合わせでの勝率

2種の13 * 13 枚の組み合わせにおける
勝率を計算してみましょう。

RANKS = "23456789TJQKA"
H_DECK = [s + r for r in RANKS for s in "H"]
D_DECK = [s + r for r in RANKS for s in "D"]
combi = [[h, d] for h in H_DECK for d in D_DECK]
result = {":".join(c):0 for c in combi}
for my_hand in combi:
  result[":".join(my_hand)] = monte_carlo_win_rate(my_hand, num_simulations=5000)

これで、13x13=169通りの結果が出せます。

これをヒートマップにしてみましょう。


勝率をヒートマップにする


import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# キーのソート用の関数
def get_rank_order(card):
    return RANKS.index(card[1])

# キーを分離してデータフレームを作成
data_list = []
for key, value in result.items():
    row_key, col_key = key.split(':')
    data_list.append({'row': row_key, 'col': col_key, 'value': value})

df = pd.DataFrame(data_list)
unique_rows = sorted(df['row'].unique(), key=get_rank_order)
unique_cols = sorted(df['col'].unique(), key=get_rank_order)

# ピボットテーブルを作成
pivot_df = df.pivot(index='row', columns='col', values='value')

# インデックスと列を順序通りに並び替え
pivot_df = pivot_df.reindex(index=unique_rows, columns=unique_cols)

# ヒートマップの作成
plt.figure(figsize=(10, 8))
sns.heatmap(pivot_df,
            cmap='RdYlGn',
            vmin=0,
            vmax=1,
            annot=True,
            fmt='.2f',
            cbar_kws={'label': 'Value'})

plt.title('Win rate for first hand combination')
plt.tight_layout()
plt.show()
heatmap

やはり、最初にワンペアを持っているだけで勝率は高くなりますね
とはいえ、それだけでは勝てないのが
このテキサスホールデムルールの面白いところ

初期手札の読み合いやベットなどの駆け引き
この辺りが組み合わさることで
ゲーム性が高くかなり面白いものになっています。

とはいえ
日本ではまだまだ、カジノがないので
ポーカーを楽しむには
単純なゲームとしてのポーカーしか出来ません

オンラインで展開されているものは
ほぼ日本国内では違法ではあるので
手を出さないように気を付けないといけません!!!

カジノが出来たら
もっともっとシミュレーションしましょう。

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

今回は年末の飲み会の余興で
よく用いられる「ビンゴゲーム」
にまつわるものを検証してみました。

解説動画はこちら



ビンゴゲームとは

知らない方は少ないと思いますが
飲み会の余興などで行われる
安易なパーティーゲームの一種です。

ルールや遊び方は
5行x5列のマス目に
1 - 75までの数字が書かれた紙が配られ

ゲームマスターが数字を選び
手持ちの紙の数値が合えば穴を開ける
縦・横・斜めで5マス分の穴が空いたらクリア
というものです。

真ん中のマス目はFreeポケットになっていて
最初から開けられる物も有ります。

そんなビンゴゲームのアルアルを
色々考えてみました。


1. ビンゴ用紙を作ってみる

プログラム上で75個の数値から
25個を選んで、並べてあげれば
ビンゴ用紙(風の出力)の完成です。

import random

numbers = [i for i in range(1,76)]

# ランダムで数値を25個取得する
select = random.sample(numbers,25)
print(select)
print()

for i,n in enumerate(select):
    if i%5==0:
        print()
    print(n,end="\t")
[23, 24, 4, 64, 71, 29, 19, 6, 58, 70, 33, 68,
13, 25, 50, 12, 63, 11, 73, 22, 20, 36, 32, 51, 2]

23 24 4 64 71
29 19 6 58 70
33 68 13 25 50
12 63 11 73 22
20 36 32 51 2

import numpy as np
import pandas as pd

df = pd.DataFrame(np.reshape(select,[5, 5]))
print(df.to_string(index=False,header=False,col_space=8))
pandasで綺麗に描画するとこんなコードです。


もっとたくさん作りたい人向けには
画像化するコードをお送りします。
import random
from PIL import Image, ImageDraw, ImageFont
import matplotlib.pyplot as plt

font = ImageFont.truetype('Arial.ttf', 32)
numbers = [i for i in range(1,76)]

# 作る個数を指定する
n = 2
for i in range(n):
    select = random.sample(numbers,25)
    im = Image.new('RGB', (500, 500), "silver")
    draw = ImageDraw.Draw(im)
    count = 0
    for x in range(5):
      for y in range(5):
        x0,x1,y0,y1 = x*100, x*100+100, y*100, y*100+100
        draw.rectangle((x0, y0, x1, y1), fill="white", outline="black", width=4)
        if count!=12:
            draw.text((x0+32, y0+32), "{0:02}".format(select[count]), (0, 0, 0), font=font, align='center')
        else:
            draw.text((x0+32, y0+32), "●", (0, 0, 0), font=font, align='center')
        count+=1
    plt.imshow(im)
    plt.axis("off")
    plt.show()
bingooo

こんな感じで真ん中フリーポケットの
ランダム数字がかかれた用紙が出来るので
あとはそれをプリントすれば良いですね。

お金をかけたく無い人には
丁度良いかもしれません。



2.ビンゴゲームにおける色々な数字

2-1.25マスの数値の並びの組み合わせ

75 個の数字から
25 個取り出して並べる順列の総数は
こんな感じの数式で表せます。

s
プログラムでは組み合わせや
順列の数を求める事ができます。

import math

n = 75
k = 25

# p = n! / (n - k)!
p = math.perm(n, k)

print(p)
print("{:,}".format(p))
815712000579973729423615859451974909952000000
815,712,000,579,973,729,423,615,859,451,974,909,952,000,000


とてつも無い桁になりますね
ビンゴカードを全通りプリントするのは
辞めた方が良さそうです。


2-2.何回くらいでビンゴになるのか


順列数は多すぎるので全通りは実験出来ません。

代わりにビンゴシミュレーターで
100万回試行してみました。
# ビンゴの場合True , ビンゴでない場合はFalse
def check_bingo(b):
    # 横
    for i in range(5):
        if sum(b[i*5:i*5+5])==0:
            return True
    # 縦
    for i in range(5):
        b1,b2,b3,b4,b5 = b[i],b[i+5],b[i+10],b[i+15],b[i+20]
        if sum([b1,b2,b3,b4,b5])==0:
            return True
    # 斜め
    d1 = [b[d*6] for d in range(5)]
    d2 = [b[d*4] for d in range(1,6)]
    if sum(d1)==0 or sum(d2)==0:
        return True
    return False

# リストの中に数値がある場合はインデックスを、ない場合は-1を返す
def find_index(b,x):
    return b.index(x) if x in b else -1

# 何ターンでビンゴしたかをカウントする
def bingo_count(bingo,numbers):
    count=0
    for num in numbers:
        index = find_index(bingo,num)
        if index!=-1:
            bingo[index] = 0
        count+=1
        if check_bingo(bingo):
            return count
        else:
            continue
    return count

import random
numbers = [i for i in range(1,76)]
random.shuffle(numbers)

n = 1000000
calc = {k:0 for k in range(1,76)}
for i in range(n):
    # ランダムで数値を25個取得してビンゴ用紙を作る
    bingo = random.sample(numbers,25)
    # 真ん中は開ける(数値0は穴開き)
    bingo[12] = 0
    ans = bingo_count(bingo,numbers)
    calc[ans]+=1

# 結果
print("総回数 : {0}回".format(n))
tmp = []
for k,v in calc.items():
    r = v / n * 100
    print("{0:02} 回目, : {1:06}回 , {2:.05}%".format(k,v,r))
    tmp.append([k,v,r])

実行するのにすごく時間が掛かります。
これを描画してみましょう。
# 描画
import matplotlib.pyplot as plt
import pandas as pd

df_b = pd.DataFrame(tmp,columns=["num","count","rate"])
df_b["cumsum"] = df_b["rate"].cumsum()

fig, ax1 = plt.subplots(figsize=(16,8))
ax2 = ax1.twinx()
ax1.bar(df_b["num"],df_b["rate"])
ax2.plot(df_b["cumsum"],color="red")
plt.show()
kakuritu


だいたい
16回くらいやれば、10%くらいの人がビンゴ
41回くらいやれば、半分くらいの人がビンゴ
49回くらいやれば、80%くらいの人がビンゴ
になるようです。




2-3.ビンゴにならずに開けられる数の最大数


1つづつ穴を開けていくと
穴の組み合わせが多すぎるため大変です。

ビンゴ用紙に25個穴が空いた状態から穴を塞いで
ビンゴにならないかどうかを判定して
測定する形にしました。
# 結果のプリント用
def print_bingo(bingo):
    for i,b in enumerate(bingo):
        if i%5==0:
            print()
        print(b,end="\t")
    print()

# ビンゴでない場合True , ビンゴの場合はFalse
def check_bingo(b):
    # 横
    for i in range(5):
        if sum(b[i*5:i*5+5])==5:
            return False
    # 縦
    for i in range(5):
        b1,b2,b3,b4,b5 = b[i],b[i+5],b[i+10],b[i+15],b[i+20]
        if sum([b1,b2,b3,b4,b5])==5:
            return False
    # 斜め
    d1 = [b[d*6] for d in range(5)]
    d2 = [b[d*4] for d in range(1,6)]
    if sum(d1)==5 or sum(d2)==5:
        return False
    return True

count = 0
all_count = 0
seq = [i for i in range(0,25)]

combi = list(itertools.combinations(seq,5))
for c in combi:
    all_count +=1

    # ビンゴを用意(1==穴あき)
    bingo = [1] * 25

    # 穴なしに戻す(0==穴なし)
    for i in c:
        bingo[i]=0

    # ビンゴでないかどうかの判定
    if check_bingo(bingo):
        print(c)
        print_bingo(bingo)
        print()
        count +=1

print(count,all_count)
(0, 6, 12, 18, 24)

0 1 1 1 1
1 0 1 1 1
1 1 0 1 1
1 1 1 0 1
1 1 1 1 0

・・・・
48 53130

結果として
穴が20個まではビンゴにならずに
開けられるパターンが存在します。

そんなに穴が開いた状態になった人
いるんでしょうかねえ

逆にめちゃくちゃ運が悪い方を
決めることが出来ます。

シミュレーション結果を用いれば
どれくらいでプレゼントが捌けるのか
計算しやすくなると思いますので
幹事の方は逆算してみると
捗るかも知れません。

今回はビンゴゲームについての
数値検証でした。

それでは。


世の中偽物ばかりです。
A●z●●ですら、コピー商品やそっくり商品ばかりで
うんざりします。

普段目にしているものの殆どは偽物ばかりなんですよ。

しかし世の中には出会った事のない
ホンモノと言うものが存在します。

解説動画はこちら




さて仮定の話ですが
今回は人類史上まだ誰も解いたことのない難問です。

問題:
もし10万シナリオに1つの確率で時間停止系が本当だとしたら
1000本のシナリオを見たときにその中に
1つ本物が含まれる確率はいくらでしょうか?

ポアソン分布に従うと仮定してみます。
ポアソン分布とは不良品の検査などで用いるもので

例えば200個に1個の割合で不良品が発生するとしたとき
10個を取り出したら、1個不良品が混じってる確率は?

と言ったような問題に使えます。

このような確率はポアソン分布に従うとされていますので
確率の計算は
スクリーンショット 2020-05-30 16.37.56
と言う式で表すことができます。

ここでは2つの数がわかれば計算出来ます。

k=出会いたい個数
λ=確率=遭遇確率*個数

kは1シナリオでも会えれば良いので 1です。
λは10万シナリオに1本なので10万分の1 * 1000本です。


早速計算してみましょう。
# 出会いたい本数
k = 1

# 試してみる本数
n = 1000

# 遭遇確率
p = 1/100000

# 確率計算
lamb = p * n
answer = (np.e ** -lamb) * (lamb ** k) / math.factorial(k)

print(answer)

答えは
0.0099

約1%程ですね。

分かりづらいので描画するのと
色々数を変えて試してみましょう。

ポアソン分布を求めるには
scipy.statsのpoisson.pmf(出会いたい本数,確率)で
求められます。

from scipy.stats import poisson
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

# 出会いたい本数
x =  np.arange(0, 21, 1)
# 試してみる本数
n = 10000
# 遭遇確率
p = 1/100000

# 確率計算
lamb = p * n
y= [poisson.pmf(k, lamb) for k in x]

# 描画
plt.figure(figsize=(16,9))
plt.bar(x, y, align="center", width=0.4, color="red",alpha=0.5, label="Poisson λ= %d" % 10)
for x1,y1 in zip(x,y):
    plt.text(x1, y1+0.05 , '{:.03}'.format(y1) , size = 10, color = "green")
    plt.text(x1, y1+0.07 , '{:.01%}'.format(y1), size = 10, color = "black")
plt.xticks(np.arange(0, 21, 1))
plt.legend()
plt.show()


結果は横軸は出会える本数で縦軸はその確率です。

色々試行本数を変えて試してみると
1万本の時は1本のホンモノに出会えるには9%程ですね。

1man

10万本だと、出会えないのが36%
1本でもホンモノに出会えるのも36%ですね!!!

10man

100万本だと出会えないのが稀になってきますね!!


100man


あくまでも10万本に1本の確率で
本物が有ると仮定した時の話で有るので
出会える保証はありません。

もっと低いかもしれないし
実はもっと高い確率かもしれない。

もし
この世に存在しないと断定するのであれば
この世の全てのシナリオを確認しなければなりませんので

きっとこの世には
有るんです!!!!!!!!!!
そう信じたいんです。

そう
信じるか信じないかは貴方次第なんです。

今回はここまでです。

それでは。

このページのトップヘ