Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

ビンゴ:リーチ後何回でビンゴになる?

More than 3 years have passed since last update.

今日はクリスマスイブ。この時期、忘年会やクリスマス会などで、一年で最も頻繁にビンゴが行われる時期なのではないでしょうか。

ビンゴの典型的なやり方として、リーチになった人がまず名乗り出て、その中から、更にビンゴになった人が名乗り出る、というものがあると思います。リーチになるとビンゴが近いのでは、と、皆、期待して待ちますが、ではリーチになってから、何回ぐらいでビンゴになれるのでしょうか?
ちゃんと確率計算すれば出来ると思いますが、とりあえず、シミュレーションで調べてみました。

Bingoカードの仕様は、Wikipediaで説明されているものを使用しました。以下、Wikipediaの当該ページから引用します。

一般的にビンゴカードはタテ・ヨコ5マスずつ、計25個のマス目が書かれている。
その内、中央を除く24マスには1から75までの番号のうち24個の番号が書かれており、
中央はフリースポットとして最初から有効な番号として扱われる。
1枚のカードの中で同じ番号が重複することはない。

ゲーム参加者全員にビンゴカードを配った後、進行役が無作為に番号を1つ選び
(ビンゴマシーンと呼ばれる専用の道具を使う場合が多い)、
手持ちのカードに同じ番号があればそのマスが有効となる。有効部分には印をつけたり
穴をあけたりして判別できるようにする。
これを繰り返し縦・横・斜めのいずれか1列が揃って有効になった場合に上がりとなり、
「ビンゴ」と叫んで上がったことを宣言する[1]。

カードに書かれる番号は、通常はまったくのランダムで配置されているわけではなく、
一番左の列は1-15の中から5個選ばれている。同様に、左から2列目は16-30、中央列は31-45、
右から2列目は46-60、一番右の列は61-75から5個ずつ(中央列のみフリースポットがあるので4個)
選ばれている[2]。

引用元:https://ja.wikipedia.org/wiki/%E3%83%93%E3%83%B3%E3%82%B4

#!/usr/bin/env python
import numpy as np
import numpy.ma as ma
np.random.seed(7)

class bingocard():
  def __init__(self):
    self.card = np.asarray([np.random.choice(range(15*i+1, 15*(i+1)+1),5,replace=False) for i in range(5)])
    self.card[(2,2)]=0
    self.rcnt = np.zeros(5, dtype=int)
    self.rcnt[2] = 1
    self.ccnt = np.zeros(5, dtype=int)
    self.ccnt[2] = 1
    self.dia_lr = 1
    self.dia_rl = 1
    self.isbingo = False

  def mask(self,val):
    pos = np.where(self.card==val)
    if len(pos[0])==0:
      return
    self.rcnt[pos[0]]+=1
    self.ccnt[pos[1]]+=1
    if pos[0]==pos[1]:
      self.dia_lr+=1
    if pos[0]==(4-pos[1]):
      self.dia_rl+=1
    self.isbingo = ((len(self.rcnt[self.rcnt==5])+len(self.ccnt[self.ccnt==5])+(self.dia_lr==5)+(self.dia_rl==5)))

  def numlizhi(self):
    return  len(self.rcnt[self.rcnt==4]) + len(self.ccnt[self.ccnt==4])+(self.dia_lr==4)+(self.dia_rl ==4)
def do_test(Ncards):
  cards = []
  numbers = range(1,76)
  np.random.shuffle(numbers)
  for i in range(Ncards):
    cards.append(bingocard())
  firstlizhi = [0] * Ncards
  firstbingo = [0] * Ncards
  bingoids = []
  for i,c in enumerate(numbers):
    for j,card in enumerate(cards):
      if j in bingoids:
        continue
      card.mask(c)
      if firstlizhi[j]==0 and card.numlizhi()>0:
        firstlizhi[j] = i
      if card.isbingo:
        firstbingo[j]=i
        bingoids.append(j)
  return np.bincount((np.array(firstbingo)-np.array(firstlizhi)))
if __name__=='__main__':
  Ntrial = 100
  Ncards = 100
  results = []

  for t in range(Ntrial):
    res = do_test(Ncards) 
    results.append(res)
  maxlen = max([len(x) for x in results])
  hist = np.zeros((len(results), maxlen))
  for i,res in enumerate(results):
    hist[i, :len(res)] = res
  histall = np.sum(hist, axis=0)
  print 'histogram: ', histall
  print 'Bingo within 5 times after lizhi', np.sum(histall[:6])
  print 'Bingo beyond 5 times after lizhi', np.sum(histall[6:])

100人でのビンゴを100回やった場合を想定し、最初にリーチになってから(firstlizhi)、ビンゴになるまでの回数(firstbingo)をカウントしています。1つの数字の読み上げを1回と数えています。
lizhiはリーチのことです。Wikipediaで初めて知りましたが、「リーチ」と名乗り出るのは日本独自の習慣で、麻雀のリーチ(立直)から来ているそうです。立直の中国語発音はli4zhi2だと思いますので、lizhiと綴りました。

bingocardクラスのインスタンスが1枚のビンゴカードのインスタンスになるように作られています。mask関数で数字をマスクしますが、マスクすると同時に、縦横斜めのカウントを行ってしまい、どこに穴が開けられているかは記憶しない実装になっています。

乱数については、Mersenne Twitsterによる擬似乱数生成器を使わないと実装上まずいとおもいますが、numpyもPythonのrandomも、デフォルトでMersenne Twisterを裏側で使うようになっているので、問題はないと思います。実験が再現できるようにnumpy.random.seed関数で乱数のシードを与えておきましょう。

で、結果は、次のようになりました。100x100なので1万回の試行です。ですから、下二桁の手前に小数点をおけば、%表示になります(例:231→2.31%)。

histogram: [   0.  231.  248.  301.  282.  317.  325.  392.  347.  356.  393.  445.
  410.  398.  417.  383.  418.  367.  346.  347.  296.  272.  306.  252.
  266.  211.  209.  166.  180.  159.  138.  115.  110.   97.   94.   65.
   64.   46.   47.   37.   31.   19.   22.   25.   11.   13.    8.    4.
    6.    3.    3.    0.    0.    2.]
Bingo within 5 times after lizhi 1379.0
Bingo beyond 5 times after lizhi 8621.0

1万回中、リーチになった後、1回でビンゴになった回数が231回、2回でリーチになった回数が248回…というように読みます。
より簡単に、リーチになった後、5回以内にビンゴになる確率と、ビンゴまで5回より多くかかる確率を計算してみたのが、最後の2行です。

リーチになった後、ビンゴまで5回よりも多くかかる確率は86.21%だそうです…
人によって感覚は違うと思いますが、5回よりも多くかかるのは、私の感覚では「結構かかる」方ですので、リーチになっても、ビンゴまで結構待たなければいけないことが大半である、という結果になりました。

yoehara
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away