清涼飲料水のキャップのオマケとして、10 種類の清涼飲料水マンのキャップがついてくるキャンペーンがありました。そこで、豪気な凛さんは 24 本の箱買いを実行しました。24 本も買えば、10 種類そろっていそうな感じですが、実際には(以下省略)そこで、そろわない場合の確率はどのくらいになるのか? 果たして凛さんは、全部の種類の清涼飲料水マンのキャップを持っているのだろうか?
ペプシ算ファイナル – 永字八法で知って、久々にパズル欲を触発されたのでやってみた。我ながらなかなかエレガント。大元ページの再帰的な計算法では手も足も出ない数になっても瞬殺。rubyのBignumが許す限り。
class Integer
def factorial
(1..self).inject(1){|r, i| r * i}
end
def combination(n)
self.factorial / (n.factorial * (self - n).factorial)
end
end
def pepsi(m, n)
result = (0..m).inject(0){|r, i| r + (-1)**i * m.combination(i) * (m - i)**n}
(result * 10000000000000000 / m**n).to_f / 10000000000000000
end
puts pepsi(ARGV[0].to_i, ARGV[1].to_i)
下のように実行するとm種類のおまけ付きのペプシn本入りを箱買いしたときにコンプできている確率を返してくれます。
ruby pepsi.rb m n
たとえば例題の通りなら、
ruby pepsi.rb 10 24
ね。それだけ。
11/27追記
combinationも整数のメソッドにしてみたりちょっと表現を整理。ロジックはまったく一緒。それと、30 300程度で計算できなくなるのは、よく見たらBignumに入りきらないって言ってるんじゃなくてFloatで表現できないと言ってるだけだった。道理で少なすぎると思った。整数だけで最後の割り算をするようにしたらもっとでかい数でもいけるようになった。
ruby pepsi.rb 365 2287
0.500370783936947
つまり誕生日が均等に分布していると仮定して2月29日を無視した場合、人口2287人以上の街では「毎日誰かしらは誕生日を迎えている」確率5割以上。へー。
おまけ
コメント