Created
October 1, 2011 10:44
-
-
Save shedd/1255865 to your computer and use it in GitHub Desktop.
Fun with Probability
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# to run this file: | |
# gem install rspec | |
# rspec prob_spec.rb | |
class Integer | |
def factorial | |
self.downto(1).inject(:*) | |
end | |
end | |
class Dice | |
attr_accessor :number_of_choices, :choice_labels, :probabilities, :sides | |
def initialize number_of_choices, choice_labels, probabilities | |
@number_of_choices = number_of_choices | |
@choice_labels = choice_labels | |
@probabilities = probabilities | |
@sides = Hash.new | |
raise "probability values do not add up to 1" unless probabilities.inject(:+) == 1 | |
choice_labels = [ choice_labels ] if choice_labels.class == String # convert to array if we're being passed a single side | |
choice_labels.each_with_index{ |choice, n| @sides.merge!( choice => probabilities[n] ) } | |
end | |
def method_missing(*args) | |
# args[0] is the method name called | |
if args.length == 2 and args[0] == :call and args[1].class == String | |
@sides[ args[1] ] | |
else | |
super | |
end | |
end | |
end | |
class Solve | |
attr_reader :dice | |
protected :dice | |
def initialize d | |
@dice = d | |
end | |
def prob_of_ordered_events events | |
events.inject(1){|product, e| product * @dice.sides[e] }.round(4) | |
end | |
def prob_of_unordered_events events | |
self.choose(events.size, events.count(events.last), nil) * prob_of_ordered_events(events) | |
end | |
def choose n, k, d | |
n.factorial / ( k.factorial * (n-k).factorial) | |
end | |
end | |
describe "Dice" do | |
context "in context to initializing class variables" do | |
it "should allow you to configure the number of sides for a dice, with each side having a label, and a unique probability" do | |
dice = Dice.new(2, ["heads","tails"], [0.5,0.5]) | |
dice.number_of_choices.should == 2 | |
dice.choice_labels.should == ["heads","tails"] | |
dice.("heads").should == 0.5 | |
dice.("tails").should == 0.5 | |
end | |
it "should fail if you give it probability values that do not add up to 1" do | |
expect { Dice.new(1,["heads"],[0.9]) }.should raise_error | |
end | |
it "should support dice with 1 side" do | |
dice = Dice.new(1,["heads"],[1.0]) | |
dice.number_of_choices.should == 1 | |
end | |
end | |
end | |
describe "Solve" do | |
it "should solve for the probability of a list of ordered events" do | |
four_sided_die = Dice.new(4, ["1","2","3","4"], [0.20,0.20,0.20,0.40]) | |
Solve.new(four_sided_die).prob_of_ordered_events(["1","4","2"]).should == 0.016 | |
end | |
it "should solve for the probability of a set of unordered events" do | |
two_sided_die = Dice.new(2,["heads","tails"],[0.5,0.5]) | |
Solve.new(two_sided_die).prob_of_unordered_events(["tails","heads"]).should == 0.5 | |
Solve.new(two_sided_die).prob_of_unordered_events(["heads","tails"]).should == 0.5 | |
end | |
it "should solve for the probability of a choice of events" do | |
one_sided_die = Dice.new(1,"only side",[1.0]) | |
#Given 3 Dice and 5 Buckets, how many ways are there to place the Dice in the Buckets | |
#Also known as k Choose n or 5 choose 3 | |
Solve.new(one_sided_die).choose(5, 3, one_sided_die).should == 10 | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment