読者です 読者をやめる 読者になる 読者になる

ガシャポンの確率論(その3)

数学 Ruby

前回まででわたしの長年の疑問であったガシャポンは何回で揃うか、という課題に解答が得られました。
考え方の順序としては、次のようになります。
1.すべての場合を数え挙げる方法で、たとえばn回で揃う確率とかをシミュレートするプログラムを作る。これだとある程度以上の計算が場合の数が増えると不可能になる。たとえば6種類のものを10回やると6の10乗の場合わけをしなければならず、その一つひとつについて6種類のセットが含まれているかどうかを検証してなってしまう。しかし、種類を限定(v<=6)し、回数を限定(n<=11)すれば確実に解が得られる。
2.確率だけだと再帰をつかったアルゴリズムがあり、n-1回目にv-1種類揃う確率からn回目にv種類揃う確率が算出できる。これも相当面倒な計算であるが、上記のすべての場合を数え上げる方法と比べるとはるかに速いので、プログラムし、上記の結果と検証する。
3.結果、5種類(v=5)のガシャポンが11回(n=11)で揃う確率が一致した(0.5225472)。回数を順に上げていくと、確率がしだいに増えて1.0に近づく。確率が0.95を超えた時点で、ほぼ偶然でなく、まず揃うということだと統計学的に判断し、6種類(v=6)の場合、27回(n=27)で0.95以上の確率で揃うという結果を得た。

さて、次に平均何回で揃うか、という課題である。前々回の記事で紹介した山本弘のページでは期待値の合計として、6種類の場合期待値の合計を平均15回かかるという言い方をしていた。たとえば6種類のうち5種類が揃っていて、最後の1個を得るのに確率は1/6で、期待値は6回。1回であたる人もいるだろうし20回でも当たらない人もいるだろうが、平均6回。ここでもう納得感がついていかないので、ここから検証。最終的には6種類をそろえるのに平均何回かかるかという計算をする。確立から算出できないかと頭をひねったのですが、あきらめて数えあげることにしました。

平均というときのイメージはたとえばあるガシャポンのセットを全部そろえた人が100人いて、それぞれに何回目で揃いましたか? と聞いてその合計を100で割る、というイメージだと思う。種類をv(variation)、mをそろえたい数、と置き、たとえばv=6ならば["a", "b", "c", "d", "e", "f"]からランダムに一つずつとっていき、数列にためていって、m=1ならば["a"]がでたらその時点までの数を数える。サンプル人数をn人とおくならばn人について同様のことをやって、かかった回数の合計をnで割れば平均。このやりかたでやると、なんと! 端数はつきますが6種類から1種類を得るための平均は6回前後。6種類全部揃えるための平均は14.7くらい。15は超えません。

#gashave.rb

#when thiking average we usually think of people who achieved the goal and how many times
#they tried to get that goal.  There can be a logical way of thinking but up to now I have not yet 

succeeded in thinking it out.
# This time I use random sample to get that average.  If we take a big number as sample, 
# maybe I can get the whole picture and it will be helpful in future thinking.

v = 6 # v is variation of the gashapon
n = 10 # n is number of people who succeeded in fullcompletion of the variation
m = 1 # m is number of the goal items that you want to collect.  This is different from the goal set 

number which we used in calculating the probability because at that time only the number is 

meaningful.  This time the set itself is important.  I mean ["a", "b"] is different from ["b", "c"].
t = 0 # t is number of trials or throws in order to get that result. For the case of variation of 2, we know 

that 2 times is 0.50 probability and 6 times is enough for 0.95 probability.  I do not yet know if this 

observation is helpful or not in solving this average problem.

def variation(v)
  ary = %w(a b c d e f g h i j k)
  return ary[0..(v- 1)]
end

def throw(m, v)
  var_ary = variation(v)
  var_len = var_ary.length
  target_ary = variation(m)
  throw_ary = 
  throw_ary << var_ary[rand(var_len)]
  while target_ary - throw_ary != 
    throw_ary << var_ary[rand(var_len)]
  end
  return throw_ary.length
end

# first I want to know the average of the number of throws for getting 1 target out of 6 variations.
v = 6
m = 6
n = 1000
sum = 0
n.times do |i|
 temp = throw(m, v)
 puts temp
 sum = sum + temp
end
printf "The average of getting #{m} target out of #{v} variations in #{n} sample is : #{sum / n.to_f}\n"