Keitho08
Keitho08

Reputation: 37

Python function that simulates rolling dice based on input parameters 1) number of dice 2) Number of rolls

I have been looking on stack and spend several hours browsing to try and solve this. Task is:
Write a Python function called dicerolls that simulates rolling dice. Your function should take two parameters: the number of dice k and the number of times to roll the dice n. The function should simulate randomly rolling k dice n times, keeping track of each total face value. It should then return a dictionary with the number of times each possible total face value occurred. So, calling the function as diceroll(k=2, n=1000) should return a dictionary like: {2:19,3:50,4:82,5:112,6:135,7:174,8:133,9:114,10:75,11:70,12:36}

So far I have managed to define the dice function but where I am struggling is to add the k(number of rolls) into the dicerolls function. What I have so far:

from numpy import random

def dice():
    return random.randint(1, 7)

def diceroll(number_of_times):
    counter = {n : 0 for n in range(2, 13)}

    for i in range(number_of_times):
        first_dice = dice()
        second_dice = dice()
        total = first_dice + second_dice
        counter[total] += 1
    return counter

diceroll(1000)

Output: {2: 19, 3: 49, 4: 96, 5: 112, 6: 150, 7: 171, 8: 151, 9: 90, 10: 89, 11: 47, 12: 26}

Any suggestions are appreciated.

Edited code after answer

import random

def diceroll(k, n, dice_sides=6):
    # prepare dictionary with zero values for all possible results
    counter = {n : 0 for n in range(k, k*dice_sides + 1)}

    # roll all the dice
    for i in range(n):
        dice_sum = sum(random.choices(range(1, dice_sides + 1), k = k))
        counter[dice_sum] += 1
    return counter

diceroll(k=2, n=1000)

Output: {2: 20, 3: 49, 4: 91, 5: 116, 6: 140, 7: 138, 8: 173, 9: 112, 10: 72, 11: 65, 12: 24}

Upvotes: 2

Views: 5118

Answers (3)

Daniel F
Daniel F

Reputation: 14399

If you really want to use numpy, this will be faster, but only noticeably faster if your have large numbers of rolls and dice:

def diceroll(k, n, dice_sides=6):
    rolls = np.random.randint(dice_sides, size = (k, n)) + 1
    counter = {k:v for k, v in zip(*np.unique(rolls.sum(1), return_counts = True))}
    return counter

diceroll(1000, 2)
Out[]: 
{2: 31,
 3: 49,
 4: 105,
 5: 120,
 6: 136,
 7: 163,
 8: 152,
 9: 109,
 10: 70,
 11: 40,
 12: 25}

Upvotes: 1

Patrick Artner
Patrick Artner

Reputation: 51633

You can leverage the random function that provides multiple rolls of the same funciton at once: random.choices(iterable, k=number of results). This is faster then rolling 1 dice multiple times and add the values up.

You would need to change your code to:

import random


def diceroll(number_of_dices, number_of_times, dice_sides=6):
    # prepare dictionary with zero values for all possible results
    counter = {n : 0 for n in range(number_of_dices, number_of_dices*dice_sides + 1)}

    # roll all the dice
    for i in range(number_of_times):
        dice_sum = sum(random.choices(range(1, dice_sides + 1), k = number_of_dices))
        counter[dice_sum] += 1

    return counter

print(diceroll(3, 100))

Output:

{ 3:  0,  4: 1,  5: 1,  6: 7,  7: 10,  8: 10,  9: 16, 10: 10, 
 11: 19, 12: 8, 13: 8, 14: 3, 15:  4, 16: 2,  17:  1, 18: 0}

Upvotes: 1

Ron Serruya
Ron Serruya

Reputation: 4426

You could use collectors.counter to keep track of the rolls.
Also, it might be down to preference, but there is no reason to import numpy for something so simple like random.

In [1]: import random

In [2]: from collections import Counter

In [3]: def dice():
   ...:     return random.randint(1,7)
   ...:


In [4]: def dice_roll(number_of_times):
   ...:     counter = Counter()
   ...:     for i in range(number_of_times):
   ...:         first_dice = dice()
   ...:         second_dice = dice()
   ...:         total = first_dice + second_dice
   ...:         counter[total] += 1
   ...:     return counter
   ...:

In [5]: def multiple_rolls(k, number_of_times):
   ...:     final_counter = Counter()
   ...:     for i in range(k):
   ...:         final_counter.update(dice_roll(number_of_times))
   ...:     return final_counter
   ...:

In [6]: multiple_rolls(2, 1000)

Out[6]:
Counter({9: 247,
         5: 170,
         10: 198,
         6: 196,
         8: 251,
         4: 123,
         12: 102,
         7: 249,
         14: 44,
         2: 44,
         11: 184,
         3: 105,
         13: 87})

Upvotes: 2

Related Questions