Home > front end >  Three dice are tossed. Get all events where is the sum of the three faces equal to 5
Three dice are tossed. Get all events where is the sum of the three faces equal to 5

Time:10-17

Three dice are tossed. Event A is the sum of the three faces equal to 5. Enumerate all outcomes for Event A in python

  1. The following works but only prints one roll of the dice equaling 5, I need help to print all possible enumerations.

  2. Also, the following prints a 2 before printing the individual dice rolls, not sure why it's doing that


test_list=[1,2,3,4,5,6]
k=6
red=[ele for ele in test_list for i in range(k)]
blue=[ele for ele in test_list for i in range(3)]  [ele for ele in test_list for i in 
range(3)]
green=[ele for ele in test_list for i in range(1)] [ele for ele in test_list for i in 
range(1)]  [ele for ele in test_list for i in range(1)]  [ele for ele in test_list for i in 
range(1)]  [ele for ele in test_list for i in range(1)]  [ele for ele in test_list for i in 
range(1)]

import pandas as pd
df=pd.DataFrame(list(zip(red, blue, green)), columns=['Red die', 'Blue die', 'Green die'])

eventA=df.sum(axis=1)
df['eventA']=eventA

#EventA=sum of outcomes is 5
sum_roll=df[df['eventA']==5]
print(sum_roll)

CodePudding user response:

This will do it:

from itertools import product

A  = [x for x in product(range(1,7), repeat=3) if sum(x) == 5]

CodePudding user response:

Initially ignoring the fact that the logic to generate the combinations of 3 dice is wrong, I am going to address your main questions first:

  1. The following works but only prints one roll of the dice equalling 5,

This is because in the DataFrame that you have generated has only one row the sum of which equals 5. If you replace 5 with 10, we can see multiple rows:

sum_roll = df[df['eventA']==10

Alternatively change the logic to generate (all) the combinations.

  1. The following prints a 2 before printing the individual dice rolls,

This is the DataFrame index being printed. One way of losing it would be as follows:

print(sum_roll.to_string(index=False))

#Output
Red die  Blue die  Green die  eventA
       2         4          4      10
       3         5          2      10
       4         2          4      10
       5         3          2      10

As mentioned above, your logic to generate the combinations is not correct. Here is a way to correctly generate a DataFrame with all the combinations with itertools.

import pandas as pd
from itertools import product

myList = list(product(range(1,7), repeat=3))
df = pd.DataFrame(myList, columns=['Red die', 'Blue die', 'Green die'])
print(df)

We must remember that there are 3 dice, there should be (6 * 6 * 6) = 216 combinations generated.

CodePudding user response:

Generating all of the possible combinations of faces of dice in this problem is way overkill. For 3 dice, this is tenable, but quickly becomes infeasible as the number of dice increases to even double digits. As the OP points out, there are a total of 216 possible rolls of 3 dice, only 6 of which total to 5.

Here is a version that only visits the necessary faces to list them all. The general intuition is to simply pick the first die, then consider the n-1 dice problem summing to total-first_die. We can enforce sorting if we only want to get the combinations, and not the permutations. You can see exactly how many nodes are visited by viewing the print statements.

""" generates integer partitions of total consisting of exactly n_dice summands
    summands are constrained from dmin to dmax.
    partition_so_far is used in the recursion, and should always be None when the user calls iterdice.
    ordered is whether to consider combinations (False) or permutations (True)
"""
def iterdice(n_dice=3, dmin=1, dmax=6, total=5, partition_so_far=None, ordered=False):
    print(n_dice, dmin, dmax, total, partition_so_far)
    # initialize your partition
    if partition_so_far is None:
        partition_so_far = []
    # recursion base case
    if n_dice == 1:
        yield partition_so_far   [total]
        return None
    # iterate over possibilities for the next die
    # if we want *combinations*, enforce sorting by updating dmin and die_max
    # note that the current die value can't be bigger than 
    #   total/n_dice (combinations)... otherwise, we'll run over with our dice.
    #   e.g. if total==5 and n_dice==3, this die can't be 2 
    #   (because the next two would have to be at least 2)
    # (alternatively, for permutations, current die value can't be bigger than 
    #   total - dmin*(n_dice-1)
    # note that the current die value can't be smaller than 
    #   total - dmax*(n_dice-1)... otherwise, we'll never get to total
    die_min = max(dmin, total-dmax*(n_dice-1))
    die_max = min(dmax, total-dmin*(n_dice-1) if ordered else int(total/n_dice) )
    for next_die in range(die_min, die_max 1):
        partition = partition_so_far   [next_die]
        yield from iterdice(n_dice-1, dmin if ordered else next_die, dmax, total-next_die, partition, ordered)
   
# test
if __name__ == "__main__":
    from pprint import pprint
    pprint(list(iterdice(3, 1, 6, 5, None, True))) 
  • Related