Ricardo Medina
Ricardo Medina

Reputation: 11

Two dice thrown and its distribution does not correspond with probabilities

In the board game Catan, you throw 2 six-sided dice every turn, the possible results go from 2 to 12 and the distribution of the sum should be something like this in 100,000 throws:

***CATAN DICE***

2 *****5998

3 ********8170

4 ********8170

5 **********10299

6 ************12283

7 **************14341

8 ************12331

9 **********10149

10 ********8090

11 ******6033

12 ****4068

However I only get this result when the dice is seven-sided from 0 to 6 using randint(0, 6). When I use randint(1,6) the distribution is the following:

***CATAN DICE***

2 **2771

3 *****5560

4 *****5560

5 ********8410

6 ***********11088

7 **************14132

8 ****************16491

9 *************13768

10 ***********11163

11 ********8220

12 *****5616

Which is wrong, the 8 is not more likely to occur in a pair of six sided dice. ¿Is something wrong in my code?, ¿could it be related to the way randint() works?

This is my code:

from random import randint

print("***CATAN DICE***")

normal = [0,0,0,0,0,0,0,0,0,0,0]

for i in range(0, 100000):
    a=randint(0, 6)
    b=randint(0, 6)
    throw = a+b
    if throw == 2:
        normal[0]+=1        
    if throw == 3:
        normal[1]+=1
    if throw == 3:
        normal[2]+=1
    if throw == 4:
        normal[3]+=1
    if throw == 5:
        normal[4]+=1
    if throw == 6:
        normal[5]+=1
    if throw == 7:
        normal[6]+=1
    if throw == 8:
        normal[7]+=1
    if throw == 9:
        normal[8]+=1
    if throw == 10:
        normal[9]+=1
    if throw == 11:
        normal[10]+=1
i=0
j=0
for i in range(len(normal)):
    print(i+2, end = " ")
    for j in range(int(normal[i]/1000)):
        print("*",end="")
    print(f"{normal[i]}\n")

Upvotes: 1

Views: 232

Answers (1)

pjs
pjs

Reputation: 19855

You made your code more complex than it need be, and in the process introduced some bugs. I eliminated the chain of if statements by calculating the index to be updated directly from the outcome throw. I eliminated looping to get the stars one-by-one, used rounding rather than integer truncation (floor) to get the number of stars, and right-justified the value of the sum. I also grouped the code into initialization, generation, and output stages to make it easy to read and easy to alter the number of trials being run. Without further ado, the code:

from random import randint

# initialize
n = 100000
count = [0 for _ in range(11)]  # less prone to a manual miscount error

# generate : no need for if's, calculate index directly from throw outcome
for i in range(n):
    throw = randint(1, 6) + randint(1, 6)
    count[throw - 2] += 1

# output
print("***CATAN DICE***\n")

for i in range(len(count)):
    stars = "" + "*" * round(count[i] / (n // 100))
    print(f"{i + 2 :>2} " + stars + f"{count[i]}")

which produces output such as:

***CATAN DICE***

 2 ***2741
 3 ******5637
 4 ********8210
 5 ***********11099
 6 **************14068
 7 *****************16659
 8 **************13821
 9 ***********11074
10 ********8365
11 ******5500
12 ***2826

It's very easy to modify this if you want die outcomes from 0 to 6 rather than from 1 to 6.


Finally, just for fun, here's a more generalized implementation so you can play around with number of dice and ranges on the dice.

from random import randint

# initialize
n = 100000      # trials
num_dice = 2    # number of dice

# low and high values for a die
die_lo = 1
die_hi = 6

min_outcome = num_dice * die_lo
num_outcomes = num_dice * die_hi - min_outcome + 1

# generate : no need for if's, calculate index directly from throw outcome
count = [0 for _ in range(num_outcomes)]
for i in range(n):
    throw = sum(randint(die_lo, die_hi) for _ in range(num_dice))
    count[throw - min_outcome] += 1

# output
print("***CATAN DICE***\n")

for i in range(num_outcomes):
    stars = "" + "*" * round(count[i] / (n // 100))
    print(f"{i + min_outcome :>3} " + stars + f"{count[i]}")

I think this illustrates the benefit of not hardwiring a chain of if statements.

Upvotes: 2

Related Questions