patternpythonMinor
Real time graph simulation of dice tossing
Viewed 0 times
realgraphsimulationtimetossingdice
Problem
When tossing a dice many many time all numbers tend to appear the same number of times, but if the number of throws is small then some numbers may appear more or less often than others, even considerably if the sample size is small enough.
This program shows a updating in real time graph of
Please ignore that the numbers on the X axis are wrong, that is a minor bug-fix for later, all of the visualization is there.
My code feels a bit messy, please help in organization and simplification:
This program shows a updating in real time graph of
SIDES bars (6 in default), each presenting how many times a number has appeared so far.Please ignore that the numbers on the X axis are wrong, that is a minor bug-fix for later, all of the visualization is there.
My code feels a bit messy, please help in organization and simplification:
import random
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
SIDES = 6
HEIGHT = 100
def update_results(results):
die_toss = random.randint(0, SIDES - 1)
return [x + (1 if i == die_toss else 0) for i, x in enumerate(results)]
def plot_points(ps):
plt.scatter(*zip(*ps))
def animate(frameno):
global x
x = update_results(x)
n, _ = np.histogram(x, SIDES)
n = x
for rect, h in zip(patches, n):
rect.set_height(h)
print(x, max(x) / float(min(x)))
return patches
if __name__ == "__main__":
x = [ 1 for _ in range(SIDES) ]
fig, ax = plt.subplots()
n, bins, patches = plt.hist(x, SIDES, normed=1, facecolor='green', alpha=0.75)
frames = 500
ani = animation.FuncAnimation(fig, animate)
axes = plt.gca()
axes.set_ylim([0, HEIGHT])
plt.show()
plt.show()
for i in range(100):
plt.bar(range(SIDES), x)
x =update_results(x)
print(x)
plt.show()
plt.clf()Solution
You are doing a lot of unneeded stuff. I completely deleted the
I made
I made the starting array start with all zeros, which is more realistic. Because of this I had to include a
I also made the y limit fix you suggested by updating it in the
for loop in the main part as well as the second plt.show. I also removed the plot_points function. None of this changed the functionality of the program, as far as I can tell.matplotlib.animation.FuncAnimation takes an optional fargs argument which contains arguments to be passed on to the animate function. So this gets rid of needing global variables.I made
update_results modify x. This makes the update_results function obsolete, because now we only need to increment the element at the index chosen by the dice, which we can inline in the animate function.I made the starting array start with all zeros, which is more realistic. Because of this I had to include a
min(x) or 1 in animate to ensure that if the minimum is 0, 1 is used. I used the fact that [0] * 3 == [0, 0, 0] to simplify the initialization.I also made the y limit fix you suggested by updating it in the
animate function and made it obvious that the first parameter of the animate function is unused by using _ for it.import random
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
SIDES = 6
def animate(_, x, patches):
die_toss = random.randrange(SIDES)
x[die_toss] += 1
for rect, h in zip(patches, x):
rect.set_height(h)
print(x, max(x) / float(min(x) or 1))
axes = plt.gca()
axes.set_ylim([0, max(x) + 1])
return patches
def main():
x = [0] * SIDES
fig = plt.figure()
n, bins, patches = plt.hist(
x, SIDES, facecolor='green', alpha=0.75)
frames = 500
ani = animation.FuncAnimation(fig, animate, fargs=(x, patches))
plt.show()
if __name__ == "__main__":
main()Code Snippets
import random
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
SIDES = 6
def animate(_, x, patches):
die_toss = random.randrange(SIDES)
x[die_toss] += 1
for rect, h in zip(patches, x):
rect.set_height(h)
print(x, max(x) / float(min(x) or 1))
axes = plt.gca()
axes.set_ylim([0, max(x) + 1])
return patches
def main():
x = [0] * SIDES
fig = plt.figure()
n, bins, patches = plt.hist(
x, SIDES, facecolor='green', alpha=0.75)
frames = 500
ani = animation.FuncAnimation(fig, animate, fargs=(x, patches))
plt.show()
if __name__ == "__main__":
main()Context
StackExchange Code Review Q#154019, answer score: 4
Revisions (0)
No revisions yet.