Skip to content

Instantly share code, notes, and snippets.

@simpl1g
Created July 31, 2015 20:49
Show Gist options
  • Save simpl1g/e8333e5ba770e5a687c1 to your computer and use it in GitHub Desktop.
Save simpl1g/e8333e5ba770e5a687c1 to your computer and use it in GitHub Desktop.
Dice sum probability calculator
require 'bigdecimal'
require 'benchmark'
class DiceSumProbabilityCalc
DEFAULT_SIDES_COUNT = 6
def initialize(sum, dices_count, dice_sides_count = DEFAULT_SIDES_COUNT)
@sum = sum
@dices_count = dices_count
@dice_sides_count = dice_sides_count
end
def call
coefficient * single_probability
end
private
def coefficient
(0..max_limit).reduce(0) do |acc, i|
acc + summand(i)
end
end
def summand(i)
(-1)**i * factorial_formula(@dices_count, i) * factorial_formula(@sum - @dice_sides_count * i - 1, @dices_count - 1)
end
def max_limit
(@sum - @dices_count) / @dice_sides_count
end
def single_probability
1.0 / (@dice_sides_count**@dices_count)
end
def factorial_formula(n, k)
BigDecimal.new(factorial(n)) / factorial(k) / factorial(n - k)
end
def factorial(n)
factorial_builder[n]
end
def factorial_builder
@factorial_builder ||= Hash.new { |memo, value| memo[value] = (1..value).reduce(1, :*) }
end
end
Benchmark.bm do |x|
x.report("M=300 N=100") { DiceSumProbabilityCalc.new(300, 100).call }
x.report("M=600 N=100") { DiceSumProbabilityCalc.new(600, 100).call }
x.report("M=900 N=300") { DiceSumProbabilityCalc.new(900, 300).call }
x.report("M=1800 N=300") { DiceSumProbabilityCalc.new(1800, 300).call }
x.report("M=2100 N=600") { DiceSumProbabilityCalc.new(2100, 600).call }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment