考える練習

舞台やイベントの感想など

おいでよ、積む積むの森 ~ 何枚買うか、それが問題だ ~

こちらのブログ記事見て、他の人がどうやって考えたかって
おもしろいなーと思ったので、今回はじめて積むにあたり、
どう考えて決めたのか、私も書いてみようと思います。

a1kavva.hatenablog.com

まずは、総応募数と当選者数

参考にできるのは販売枚数。
また同じブログになっちゃいますが、こちらの記事を参考に予想しました。

a1kavva.hatenablog.com

同じく接近戦があった Such a beautiful affair が 21000 だったので、
今回もそれぐらいではないかなということで 21000 と予想。
(って、今あらためて数字見直したら約22000ですね;)
実際には購入者全員が応募するわけではないので、応募数はこれより少なくなるはず、
ではあるんですが、少なめに見積もって外れたら嫌だしなーということで、
この数をそのまま使用しました。

当選者数は5箇所合計で 1150人。

何枚買ったら何%なのか

んで、ここからです。

単純倍率も十分参考にはなるけど、実際何枚買ったら何%なのか知りたいなーと悶々。
Such a beautiful affair の時に、Excel 使って確率計算したはずなんですが、
どうやって考えたか忘れてしまった私。

「はっ、プログラム組んでシミュレートしちゃえばいいじゃん!」

ということで、以下のようなプログラムを書き書き。

1. 応募総数分の要素を持つ配列を作成
2. 当選者数分の当たりをランダムに配列に入れる
3. 配列の先頭から、購入枚数分をチェック、当たりが含まれるかを見る。
(厳密にやるなら先頭からではなく、ランダムにやらないとたぶんダメですが;)
…というのを 10000 回実行し、当選回数/10000回 を求める。

実行結果

応募総数 21000 で実行した結果は以下。
左端の数字が購入枚数、次が確率です。

total: 21000, win: 1150, ratio:18.26086956521739
 1.0  5.75% ( win : 575, try : 10000 )
 10.0  42.22% ( win : 4222, try : 10000 )
 20.0  68.01% ( win : 6801, try : 10000 )
 30.0  81.67% ( win : 8167, try : 10000 )
 40.0  90.05% ( win : 9005, try : 10000 )
 50.0  94.1% ( win : 9410, try : 10000 )
 60.0  96.64% ( win : 9664, try : 10000 )
 70.0  98.18% ( win : 9818, try : 10000 )
 80.0  98.87% ( win : 9887, try : 10000 )
 90.0  99.39% ( win : 9939, try : 10000 )
 100.0  99.55000000000001% ( win : 9955, try : 10000 )

一番上の行の ratio が倍率なんですが、
単純倍率は約18.3倍なのに、20枚買っても 68% なんですよね。
これ実行する前に、だいたい倍率20倍かー、たぶんちょうどだとダメだろうから、
30枚くらい必要かな?と思ってたのとだいたいあってるなーと嬉しくなったのを
覚えてます。


ちなみに、応募総数をちょっと減らした場合については以下。
上にあげたブログ記事に書いてあったように、実質倍率 15倍だとしたら、
17000 あたりですが、その場合10枚で50%なので、(下記、★のところ)
とりあえず店舗特典分だけ購入でも一応期待できる確率ではありますね。

total: 17000, win: 1150, ratio:14.782608695652174
 1.0  6.83% ( win : 683, try : 10000 )
 10.0  50.38% ( win : 5038, try : 10000 )  <- ★
 20.0  75.3% ( win : 7530, try : 10000 )
 30.0  87.75% ( win : 8775, try : 10000 )
 40.0  94.04% ( win : 9404, try : 10000 )
 50.0  97.06% ( win : 9706, try : 10000 )
total: 18000, win: 1150, ratio:15.652173913043478
 1.0  6.25% ( win : 625, try : 10000 )
 10.0  47.75% ( win : 4775, try : 10000 )
 20.0  73.63% ( win : 7363, try : 10000 )
 30.0  86.14% ( win : 8614, try : 10000 )
 40.0  93.2% ( win : 9320, try : 10000 )
 50.0  96.50999999999999% ( win : 9651, try : 10000 )
total: 20000, win: 1150, ratio:17.391304347826086
 1.0  5.62% ( win : 562, try : 10000 )
 10.0  44.379999999999995% ( win : 4438, try : 10000 )
 20.0  69.94% ( win : 6994, try : 10000 )
 30.0  82.66% ( win : 8266, try : 10000 )
 40.0  91.02% ( win : 9102, try : 10000 )
 50.0  94.44% ( win : 9444, try : 10000 )

おまけ

書いたプログラムをぺたり。
Ruby という言語で書いてます。

  1 #! /usr/bin/env ruby
  2
  3 def simulate (total, win, purchase)
  4   total    = total.to_f     # 応募総数
  5   win      = win.to_f       # 当選者数
  6   purchase = purchase.to_f  # 購入枚数
  7
  8   # 試行回数
  9   try = 10000
 10   try_ary = Array.new(try, 0)
 11
 12   for i in 0...try
 13     # 応募総数分の要素を持つ配列を作成
 14     total_ary = Array.new(total, 0)
 15     # 当たりを仕込む
 16     random = Random.new
 17     for j in 0...win
 18       while 1
 19         num = random.rand(total)
 20         if total_ary[num] == 0
 21           total_ary[num] = 1
 22           break
 23         end
 24       end
 25     end
 26
 27     # 先頭から purchase 分ひき、あたりが含まれるか
 28     # FIXME 厳密にやるなら、先頭からではなく、ランダムにやるべき
 29     try_ary[i] = if total_ary[0...purchase].find {|v| v == 1}
 30                    1
 31                  else
 32                    0
 33                  end
 34   end
 35
 36   # 当選した回数を数える
 37   hit_num = try_ary.count {|v| v == 1}
 38
 39   # 当選確率を求める
 40   percent = hit_num.to_f / try.to_f * 100
 41
 42   # 結果表示
 43   puts " #{purchase}  #{percent}% ( win : #{hit_num}, try : #{try} )"
 44 end
 45
 46 #####  main #####
 47
 48 # 当選者数
 49 win_num = 1150
 50
 51 # 応募総数を変えて試行
 52 [17000, 18000, 20000].each do |total_num|
 53
 54   puts "total: #{total_num}, win: #{win_num}, ratio:#{total_num.to_f/win_num.to_f}"
 55
 56   # 購入枚数を変えて試行
 57   [1,10,20,30,40,50].each do |purchase|
 58     simulate(total_num, win_num, purchase)
 59   end
 60   puts ""
 61 end