Reputation: 37
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
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
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
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