Reputation: 1632
I would like help in finding a better approach to making my probabilty of dice program.
Here is all my code:
import random,collections
probabiltyOfDice = {}
rolls = 100
#Counters
counter1 = 0
counter2 = 0
counter3 = 0
counter4 = 0
counter5 = 0
counter6 = 0
for x in range(rolls):
output = random.randint(1,6)
if output == 1:
counter1 += 1
probabiltyOfDice[1] = counter1
elif output == 2:
counter2 += 1
probabiltyOfDice[2] = counter2
elif output == 3:
counter3 += 1
probabiltyOfDice[3] = counter3
elif output == 4:
counter4 += 1
probabiltyOfDice[4] = counter4
elif output == 5:
counter5 += 1
probabiltyOfDice[5] = counter5
elif output == 6:
counter6 += 1
probabiltyOfDice[6] = counter6
ordered = collections.OrderedDict(sorted(probabiltyOfDice.items()))
print(ordered)
My approach works and here is the output if the constant number of rolls is set to 100:
OrderedDict([(1, 15), (2, 16), (3, 14), (4, 22), (5, 21), (6, 12)])
The OrderedDict displays the dice number and along with it how many times that number appeared. I am able to work this out by using 6 counter variables and using a set of if-elif
statements.
I am using the collections library for ordering the dictionary for displaying. But I would like it if someone could show me a better way of tackling this problem.
Clearly using 6 variables and many if
statements might be a long-winded approach to this situation.
Upvotes: 1
Views: 75
Reputation: 319
So, python has a very convenient dictionary subclass called Counter, that in essence, is very fast at calculating counts. I crafted the following:
import random
from collections import Counter
prob = Counter([random.randint(1,6) for _ in range(10000)])
print(prob)
>> Counter({1: 1650, 2: 1750, 3: 1679, 4: 1546, 5: 1686, 6: 1689})
Now, the problem with that is that it can only work up to a reasonable large range. So, in order to avoid creating an intermediate list, we can have the following: import random from collections import Counter
prob = Counter()
for _ in range(10000000):
prob[random.randint(1,6)] += 1
print(prob)
>> Counter({1: 13084052,
2: 13087518,
3: 13090177,
4: 13086193,
5: 13081778,
6: 13085341})
edit: Adding a third version, which is basically the first, giving up the intermediate list for the much more convenient generator, as @Mark Dickinson suggested:
import random
from collections import Counter
prob = Counter(random.randint(1,6) for _ in range(1000000))
print(prob)
>> Counter({1: 166503, 2: 166833, 3: 166531, 4: 166681, 5: 166846, 6: 166606})
Upvotes: 2
Reputation: 476659
We can simplify the code by using a list. Here the list contains six elements, initially all set to zero:
import random, collections
rolls = 100
#Counters
counters = [0] * 6
for x in range(rolls):
output = random.randint(1,6)
counters[output-1] += 1
ordered = collections.OrderedDict(enumerate(counters, 1))
print(ordered)
For a run, it prints on my machine:
>>> print(ordered)
OrderedDict([(0, 12), (1, 11), (2, 17), (3, 31), (4, 14), (5, 15)])
We can slighly improve the efficiency of the code by generating a number between 0
and 5
(both inclusive):
rolls = 100
#Counters
counters = [0] * 6
for x in range(rolls):
output = random.randint(0, 5)
counters[output] += 1
ordered = collections.OrderedDict(enumerate(counters, 1))
print(ordered)
Upvotes: 2