0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

pythonでBINGO達成するまでの試行回数シミュレータを作成してみた

0
Posted at

久しぶりに(実務以外で)手を動かしたくなったので作ってみました。

よくあるド真ん中が最初から開いてるBINGOカードで、1列BINGO達成するまでにボールを何個取り出す?というシミュレータです。

だいたい45回ぐらいが中央値になるんですね。

bingo.py

import random
import copy
import collections
import matplotlib.pyplot as plt

class BingoSimulator():

    # 試行回数(変更可)
    STEPS = 1000000

    # 定数
    B_LIST = list(range(1,16))
    I_LIST = list(range(16,31))
    N_LIST = list(range(31,46))
    G_LIST = list(range(46,61))
    O_LIST = list(range(61,76))
    BALLS = list(range(1,76))

    PIPE = " | "
    LINE = "----------------------------"

    # BINGO達成までの積先回数を格納するリスト
    times_to_bingo_list = []
   
    def print_card(self):
        """BINGOカード出力用関数"""
        print(self.LINE)
        for i in range(5):
            print(self.PIPE + '{:>2}'.format(self.card[0][i]) + self.PIPE +\
                str(self.card[1][i]) + self.PIPE + str(self.card[2][i]) +\
                self.PIPE + str(self.card[3][i]) + self.PIPE + str(self.card[4][i]) + self.PIPE)
            print(self.LINE)

    def simulator(self):
        """1ゲーム単位のシミュレートを行う関数"""
    
        # 1-75番までのボールをセット
        tmp_balls = copy.deepcopy(self.BALLS)

        # 各縦列に入る値をランダムに5個取得
        self.card = [
            random.sample(self.B_LIST, 5),
            random.sample(self.I_LIST, 5),
            random.sample(self.N_LIST, 5),
            random.sample(self.G_LIST, 5),
            random.sample(self.O_LIST, 5),
        ]

        # 真ん中をフリーに置換
        self.card[2][2] = " F"

        # 取り出し済みボールのリスト
        self.popped_list = []
        
        # 穴が開いた座標を格納するリスト(初期値はフリー部分)
        self.punched_pos_list = [(2, 2)]

        # BINGO達成するまで処理をループ
        while len(tmp_balls) > 1:

            # ボールを1個取り出し
            pop_num = tmp_balls.pop(random.randint(0, len(tmp_balls)-1))

            # ボールに書かれた番号がカード内に存在するか確認
            for i in range(len(self.card)):
                if pop_num in self.card[i]:
                    # 存在した場合は座標を取得して穴開け
                    self.punched_pos_list.append((i, self.card[i].index(pop_num)))
            
            # 取り出したボールを取り出し済みのリストに格納
            self.popped_list.append(pop_num)

            # BINGO達成確認
            if self.judge_bingo() == True:
                break

        # BINGO達成していたら、取り出したボールの数をリストに格納して記録する
        self.times_to_bingo_list.append(len(self.popped_list))
    
    def judge_bingo(self):
        """BINGO達成判定を行う関数"""

        # n行目BINGO判定
        for i in range(5):
            if (i, 0) in self.punched_pos_list and\
                    (i, 1) in self.punched_pos_list and\
                    (i, 2) in self.punched_pos_list and\
                    (i, 3) in self.punched_pos_list and\
                    (i, 4) in self.punched_pos_list:
                return True
        
        # n列目BINGO判定
        for i in range(5):
            if (0, i) in self.punched_pos_list and\
                    (1, i) in self.punched_pos_list and\
                    (2, i) in self.punched_pos_list and\
                    (3, i) in self.punched_pos_list and\
                    (4, i) in self.punched_pos_list:
                return True
        
        # ナナメBINGO判定-1
        if (0, 0) in self.punched_pos_list and\
                (1, 1) in self.punched_pos_list and\
                (2, 2) in self.punched_pos_list and\
                (3, 3) in self.punched_pos_list and\
                (4, 4) in self.punched_pos_list:
            return True

        # ナナメBINGO判定-2
        if (0, 4) in self.punched_pos_list and\
                (1, 3) in self.punched_pos_list and\
                (2, 2) in self.punched_pos_list and\
                (3, 1) in self.punched_pos_list and\
                (4, 0) in self.punched_pos_list:
            return True
        
        return False

    def simulator_main(self):
        """ループ処理と結果出力を行う関数"""
        for i in range(1000000):
            self.simulator()

        # 結果を取り出し
        collect = collections.Counter(self.times_to_bingo_list)

        # 取り出した結果をkey順に並べ替え
        result = sorted(collect.items())

        times_list = []
        count_list = []

        # key順に並べ替えた結果をリストに格納
        for i in result:
            times_list.append(i[0])
            count_list.append(i[1])
        
        # グラフ表示
        plt.plot(times_list, count_list)
        plt.show()


def main():
    """メイン関数"""
    bingo_obj = BingoSimulator()
    bingo_obj.simulator_main()


if __name__ == "__main__":
    main()
0
0
1

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?