CElliott
CElliott

Reputation: 151

Need to output the top 3 outcomes of rolling 2 dice, which have a variable number of sides

The following code computes the probability distribution of outcomes of rolling two dice with a variable number of equal sides:

def compute_probability_distribution(sides):
  dist = {x+y: 0 for x in range(1, sides+1) for y in range(1, sides+1)}
  for die_1 in range(1, sides+1):
    for die_2 in range(1, sides+1):
      dist[die_1+die_2] = dist[die_1+die_2] + 1
  probs = dist.items()
  print "Prob dist: ", probs

E.g., for ordinary 6-sided dice the prob dist is [(2,6),(3,2),(4,3),(5,4),(6,5),(7,6),(8,5),)(9,4),(10,3),(11,2),(12,1)], where the first element of each tuple is the sum of the 2 dice, and the second element is the number of ways it can occur on one roll. Can anyone tell me how to sort the above prob dist list by the second element of each tuple so I can output the top (1 or 3) most likely occurrences? I am thinking of using the built-in list sort with some sort of comparison function.

Upvotes: 3

Views: 690

Answers (3)

MSeifert
MSeifert

Reputation: 152755

You can do it with a nested comprehensions but you can also compute the most common values by hand if you know the number of sides.

In order of increasing probability:

  • 2 and sides+sides which only have one "chance".
  • Then 3 and sides+nsides-1 which have 2.
  • 4 and sides+nsides-2 have 3
  • ...
  • Finally sides+1 has the highest probability which is just sides.

If you don't trust me look at the probability distribution for different numbers of sides.

So to get the 3 most common values, you can simply calculate them based on the number of sides:

def compute_probability_distribution(sides):
    print([(sides+1, sides), (sides, sides-1), (sides+2, sides-1)])

However, that only works for dices with at least 2 sides. For a single side dice the result will be weird with this function.

Upvotes: 2

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477309

I would simply use the data structure that is designed for this: a Counter:

from collections import Counter

def compute_probability_distribution(sides):
  dist = Counter(die_1 + die_2 for die_1 in range(1, sides+1)
                               for die_2 in range(1, sides+1))
  probs = dist.most_common(3)
  print "Prob dist: ", probs

For two 6-dices, this then will produce:

>>> compute_probability_distribution(6)
Prob dist:  [(7, 6), (6, 5), (8, 5)]

So we obtained six times a sum of seven; five times a sum of six; and five times a sum of eight.

In case you want to make the number of dices arbitrary, you can use:

from collections import Counter
from itertools import product

def compute_probability_distribution(sides,ndices=2,common=3):
  dist = Counter(sum(d) for d in product(range(1,sides+1),repeat=ndices))
  probs = dist.most_common(common)
  print "Prob dist: ", probs

So now we can calculate the 10 most common sums when we roll three 5-dices:

>>> compute_probability_distribution(5,3,10)
Prob dist:  [(9, 19), (8, 18), (10, 18), (7, 15), (11, 15), (6, 10), (12, 10), (5, 6), (13, 6), (4, 3)]

Upvotes: 1

Alexander
Alexander

Reputation: 109686

probs = [(2,6),(3,2),(4,3),(5,4),(6,5),(7,6),(8,5),(9,4),(10,3),(11,2),(12,1)]

>>> sorted(probs, key=lambda x: x[1])  # x[1] is second element of tuple pair.
[(12, 1),
 (3, 2),
 (11, 2),
 (4, 3),
 (10, 3),
 (5, 4),
 (9, 4),
 (6, 5),
 (8, 5),
 (2, 6),
 (7, 6)]

Upvotes: 2

Related Questions