LoginSignup
3
3

More than 5 years have passed since last update.

Python でビンゴゲーム の確率シミュレーションしてみた

Last updated at Posted at 2015-01-02

いきなりコード

Bingo.py
# -*- coding: utf-8 -*-

u"""BINGO の確率をシミュレーションするスクリプト
input:
    times = 抽選機を回す回数, card_num = カードの数
outpu:
    1本でも揃う確率

"""
import sys
from random import sample

# 穴
HIT = True
NOHIT = False


def generate_card():
    u"""カードを生成
    5x5で中心(3行3列)に穴が空いたカード
    B(1列目) 1 - 15
    I(2列目) 16 - 30
    N(3列目) 31 - 45
    G(4列目) 46 - 60
    O(5列目) 61 - 75
    :returns: array card, length=25

    """
    cards = []
    for i in range(5):
        cards.extend(sample(range(15 * i + 1, 15 * (i + 1)), 5))
    cards[12] = HIT
    return cards


def check_bingo(card):
    u"""BINGOしているかどうか
    判定のみかえす
    param: array
    :returns: boolean
    """
    if card.count(HIT) < 5:
        return False
    for i in range(5):
        if NOHIT not in card[i * 5: (i + 1) * 5]:
            return True
    for i in range(5):
        if NOHIT not in card[i: i + 21: 5]:
            return True
    if NOHIT not in card[0: 24: 6]:
        return True
    if NOHIT not in card[4: 21: 4]:
        return True
    return False


def print_card(card):
    for i, v in enumerate(card):
        if v == HIT:
            v = "o"
        elif v == NOHIT:
            v = "x"
        sys.stdout.write("%3s" % str(v))
        if (i % 5 == 4):
            print()
    print()


try:
    times = int(sys.argv[1])
except IndexError:
    times = 5
try:
    card_num = int(sys.argv[2])
except IndexError:
    card_num = 10000

hit_count = 0
for i in range(card_num):
    card = generate_card()
    lots = sample(range(1, 76), times)
    card_hole = [(HIT if (x == HIT or x in lots) else NOHIT) for x in card]
#    print_card(card)
#    print_card(card_hole)
    if check_bingo(card_hole):
        hit_count += 1

print(str(times) + u"回目で1本でもBINGOしてる確率:")
p = hit_count / card_num
print("%s (%.1f %%)" % (str(p), p * 100))

Gist: https://gist.github.com/0c11f757334ba9ef7b1f

入力:
抽選機を回す回数
カードの数(シミュレーション回数)
output:
一本でもBINGOする確率

それぞれの関数の説明はコメントで大方わかるはず
1. カードの生成
2. 引かれたくじの一括生成
3. カードに穴を開ける
4. BINGO判定
のループ

Pythonらしい書き方が出来た部分
card(BINGOカード) について当たりが出ているかどうかを判定する部分がPythonらしい書き方が出来たと思う(ぶっちゃけここの処理を作ってみたかっただけ)

# 4列目の判定
NOHIT not in card[3:3 + 21:5]
# 左上から右下斜めの判定
NOHIT not in card[0:24:6]

Pythonの配列は array[start :end :step] で取り出せるのでスマートに判定が書ける

実行出力例

>> python3 bingo.py 5 10000
5回目で1本でもBINGOしてる確率:
0.0003 (0.0 %)

関係ないけど今回Pythonのコーディング規約として今回Flake8で覚えたこと
関数同士の間は2行開けないといけない
配列コロンの右側にスペースを入れてはいけない(引数のカンマと同じ)

docブロックの書き方がいまいちまだわからないので勉強していこうと思う

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3