ガシャポン(ガチャポン)でセットをそろえる(フルコンプリートする)のにいくらかかるか(たとえば90%の確率で)、確率(たとえば10回で揃う確率)は? 平均何回で揃うか? という種類の質問は、「たとえば」ということばが象徴するように、個人的な思いがあったりして、なかなかちゃんと議論できません。というかバカと言われようが、納得できなかったりします。
Yahoo知恵袋に「5種類入りののガチャガチャがあり、それを10回分買って5種類全部揃えれる確率を教えてください。」という質問があって
http://detail.chiebukuro.yahoo.co.jp/qa/question_detail.php?qid=1211774567
ベストアンサーが順列組合せを使って説明していて
p(10,5) = 0.5225472
となっています。これはむずかしい。
山本弘のSF基地よりというサイト(http://homepage3.nifty.com/hirorin/gchaponkakuritsu.htm)で、「コンプリートするのにいくらかかる?」というのに、次のような説明があります。
残りの個数、期待値(回)、金額(円)
6、 1.0、 200
5、 1.2、 240
4、 1.5、 300
3、 2.0、 400
2、 3.0、 600
1、 6.0、 1200
合計 14.7、 2940
この例では、6種類のセットをそろえるのに平均約15回(つまり3000円)かかるということで、同じ考え方でYahoo知恵袋の質問の5種類で考えると、1回目は1回、2回目はのこり4個なので4/5の確率=>5/4=>1.25(平均1.25回でゲット)、3回目はのこり3個なので、3/5の確率=>5/3=>1.66、4回目はのこり2個なので、2/5=>5/2=>2.5、5回目はのこり1個なので1/5=>5/1=5.0。合計すると1.0+1.25+1.66+2.5+5.0 => 11.41。となり、平均12回で5種類がそろうことになります。
これが先ほどのYahoo知恵袋の回答10回で確率0.52と感覚が合うかどうか? 山本氏の文章は、「最後の1種類を出すのに平均して6回、1200円も注ぎこまなくてはいけません」というように、平均という言葉の定義が「期待値」と同義になっている。
実際にガシャポンを何度もやってみたり、さいころを振ったりするのは不可能なので、プログラムしてみます。
5種類を[”a”, “b”, “c”, “d”, “e”]とおいて、たとえば2回やってみるとすると場合は[”a”, “a”](”a”が2回続けて出てしまう)から[”e”, “e”]までの5の2乗の場合がありえて、そのうちたとえば ”a”がひとつでも含まれる組合せが何回あるか、というプログラムになります。この場合は25回中9回にありましたので、確立は9/25 = 0.36。山本さんの文章に沿うと最後の1個は平均5回かかることになってしまいますが、むろん100回やって当たらない場合もあるし、1回で当たってしまう場合もある。5回やるとすると、5の5乗(3125)の場合中、2101に”a”がありますので、ここだけで言えば確率0.67232で大きく0.5をオーバーしています。これは”a”が当たらない確立の5乗と考えた方がわかりやすくて、rubyですと、ruby -e’puts (4.0/5)**5) => 0.32768で合計すると1になります。
10回分買って5種類全部揃えれる確率というのは5の10乗(9765625)の場合について、[”a”, “b”, “c”, “d”, “e”]が全部含まれる場合の数の比率ですので、これはたいへん。[”a”, “a”, “a”, “a”, “a”, “a”, “a”, “a”, “a”, “a”]から[”e”, “e”, “e”, “e”, “e”, “e”, “e”, “e”, “e”, “e”]のすべての場合について、順序を問わず、[”a”, “b”, “c”, “d”, “e”]が全部含まれる場合を数えていく。rubyだと配列の引き算で結果がゼロ[]の場合とか、配列のメソッドでuniqとsizeを使って、ダブりをとってサイズが5のものの数を数えるとかができます。いずれにしてもベラボーな時間がかかるので配列を使わず1〜5**10について数字で調べていくのがいいかもしれません。この結果5103000回コンプリートしていましたので、5103000/9765625 => 0.5225472とYahoo知恵袋と同じ結果になりました。たぶん合っているのでしょう。
次の課題は90%の確率で揃うためには何回やらなければならないか?
フツー平均何回で揃うのか?
この二つの課題は実はおんなじでフツーというのがその人にとって何%により、何回で揃うという言い方が可能になるのだと思います。90%に置くとちょっと時間的に無理そうなので、70%として、種類数を2から始めます。
ruby gashapon.rb 2 3 => 6 / 8 =>0.75
ruby gashapon.rb 3 6 => 540 / 729 => 0.740740740740741
ruby gashapon.rb 4 9 => 186480 / 262144 => 0.71136474609375
4種類のセットならば9回やって初めて70%を超える確率でコンプリートする。
さて、5種類のセットで12回くらいで70%を超えるかどうか、ですが、パソコンで1時間経っても計算中なのでプログラムを見直し中です。
一応11回では60%でした。
ruby gashapon.rb 5 11 => 29607600 / 48828125 => 60.6363648
ちなみにgashapon.rbは現在下記のとおり(使っていない部分もあります)。
#! /usr/bin/env ruby # gashapon.rb num1 num2 # the first number is the number of goal set # the second number is the number of tries # for example the set is made of 2 pieces a and b, and if you take 2 times, # the possibilities are [a a], [a b], [b a], [b b] in which [a b] and [b a] is the success # namely gashapon(2, 2) is 0.5 def check_argv exit if ARGV.length != 2 end def target(num) ary = %w(a b c d e f g h i j k) return ary[0..(num- 1)] end def num2ary(number, base, digit) ary = digit = digit - 1 while digit > 0 ary.push(target(base)[number / base ** digit]) if (number / base ** digit) > 0 number = number - (base ** digit)*(number / base ** digit) end digit = digit - 1 end ary.push(target(base)[number]) end def cases(base, digit) i = 0 ary = while i < (base ** digit) ary.push(num2ary(i, base, digit)) i = i + 1 end return ary end def num_cases(base, digit) return base ** digit end def num_hitcases(case_ary, target_ary) num = 0 case_ary.each {|ary| if target_ary - ary == [] num = num + 1 end } return num end def num_hit(base, digit) i = 0 num = 0 while i < (base ** digit) num = num + 1 if num2ary(i, base, digit).uniq.length == base i = i + 1 end return num end check_argv base = ARGV[0].to_i digit = ARGV[1].to_i p child = num_hit(base, digit) p mother = num_cases(base,digit) p child.to_f / mother