# Probability Calculator - 2 stupid questions I'm stuck on

Hey guys, I’m stuck on 2 issues.

1 - When I run the experiment, i get an error on test #1 which according to the test_module.py should return expected = [“red”,“red”,“red”,“blue”,“blue”], which is exactly what my code returns. However the test indicated that it should return:

• [‘green’,
• ‘green’,
• ‘blue’,
• ‘blue’,
• ‘green’,
• ‘green’,
• ‘blue’,
• ‘green’,
• ‘blue’,
• ‘green’,
• ‘red’,
• ‘red’,
• ‘red’,
• ‘red’,
• ‘red’,
• ‘blue’,
• ‘blue’]

2 - I keep getting None as a result for my sort method, which I am using to compare the strings. I’ve looked everywhere and I can’t figure out what is going on.

``````    if drawn.sort() == expected.sort():
M +=1
``````

Below is my replit code

``````import copy
import random
# Consider using the modules imported above.

class Hat:

contents = []
drawn = []

def __init__(self,**data):
v = 0
for key,value in data.items():
while v < value:
self.contents.append(key)
v+=1
v=0
# print(contents)

def __str__(self):
a = str(self.contents)
return a

def draw(self,number):
if number <= len(self.contents):
for n in range(number):
n = random.randint(0,len(self.contents)-1)
self.drawn.append(self.contents.pop(n))
# print(len(self.contents))
return self.drawn
else:
for n in range(len(self.drawn)):
self.contents.append(self.drawn.pop(0))
return self.drawn

def experiment(hat, expected_balls, num_balls_drawn, num_experiments):

prob = 0
# print("hat is ",hat)
M = 0

expected = []
v=0
for key,value in expected_balls.items():
while v < value:
expected.append(key)
v+=1
v=0

for n in range(num_experiments):
drawn = []
myhat = hat
drawn = myhat.draw(num_balls_drawn)

if drawn.sort() == expected.sort():
M +=1
#print(M)

#essa linha zera drawn e myhat
myhat.draw(len(hat.contents)+1)

prob = M / num_experiments

return prob

``````

Link to the challenge:

These are class variables and not instance variables as they are declared here. So all objects of that class are using the same bit of memory (and values) for those variables.

Check the documentation. This is the documented behavior of the sort method on lists.

Jeremy,

Thanks for the answer. I was able to get through the questions but now i’m at the last bit: my probability is off by just a little bit.

I referred to this forum post that had the same issue but the hint you described there
still didn’t get me to realize what I am doing wrong. I am getting a 0.259 != 0.272 within 0.01 delta (0.013000000000000012 difference) : Expected experiment method to return a different probability.

below is my code:

``````import copy
import random
# Consider using the modules imported above.

class Hat:

contents = []
drawn = []

def __init__(self,**data):
v = 0

self.contents.clear()
self.drawn.clear()
for key,value in data.items():
while v < value:
self.contents.append(key)
v+=1
v=0
# print(contents)

def __str__(self):
a = str(self.contents)
return a

def draw(self,number):
if number <= len(self.contents):
for n in range(number):
n = random.randint(0,len(self.contents)-1)
self.drawn.append(self.contents.pop(n))
# print(len(self.contents))
return self.drawn
else:
for n in range(len(self.drawn)):
self.contents.append(self.drawn.pop(0))
return self.drawn

def experiment(hat, expected_balls, num_balls_drawn, num_experiments):

prob = 0
# print("hat is ",hat)
M = 0

expected = []

v=0
for key,value in expected_balls.items():
while v < value:
expected.append(key)
v+=1
v=0

for n in range(num_experiments):
drawn = []
myhat = hat
drawn = myhat.draw(num_balls_drawn)

sdrawn = sorted(drawn)
# print(sdrawn)
sexpected = []
sexpected = sorted(expected)
# print(sexpected)

# print(M)
for s in expected:
if s in sdrawn:
sdrawn.remove(s)
sexpected.remove(s)
# print(sdrawn)
# sdrawn.
if sexpected == []:
M+=1

#essa linha zera drawn e myhat
myhat.draw(len(hat.contents)+1)

prob = M / (num_experiments)

return prob

``````

Not sure if this deserves a new post

I would just delete these lines instead of messing around with clearing the contents. Using class variables like this can lead to very confusing results.

Hey Jeremy, if I delete these lines I get an error that the Hat class doesn`t have contents as an attribute.

Is this related to my probability being a little off or is it just code optimization?

Thanks

You delete those lines and then you need to fix your initialization to accommodate that change.

Hello,

My probability is a little off. From what I have read, previous users have had troubles calculating the probability.

I get the following error:
AssertionError: 0.259 != 0.272 within 0.01 delta (0.013000000000000012 difference) : Expected experiment method to return a different probability.

I’ve tried troubleshooting my code but I can’t figure out which situation I am calculating the probability wrong.

``````import copy
import random
# Consider using the modules imported above.

class Hat:

def __init__(self,**data):
v = 0

self.contents=[]
self.drawn=[]
for key,value in data.items():
while v < value:
self.contents.append(key)
v+=1
v=0
# print(contents)

def __str__(self):
a = str(self.contents)
return a

def draw(self,number):
if number <= len(self.contents):
for n in range(number):
n = random.randint(0,len(self.contents)-1)
self.drawn.append(self.contents.pop(n))
# print(len(self.contents))
return self.drawn
else:
for n in range(len(self.drawn)):
self.contents.append(self.drawn.pop(0))
return self.drawn
def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
prob = 0
# print("hat is ",hat)
M = 0

expected = []

v=0
for key,value in expected_balls.items():
while v < value:
expected.append(key)
v+=1
v=0

for n in range(num_experiments):
myhat = copy.copy(hat)
drawn = myhat.draw(num_balls_drawn)

sdrawn = copy.copy(drawn)
# print(sdrawn)
sexpected = copy.copy(expected)
# print(sexpected)

# print(M)
for s in expected:
if s in sdrawn:
# print("drawn: ",sdrawn)
# print("expected: ",sexpected)
sdrawn.remove(s)
sexpected.remove(s)
# print(sdrawn)
# sdrawn.
else:
break
if sexpected == []:
# print("success drawn: ",sdrawn)
# print("success expected: ",sexpected)
M+=1
# print(M)
#essa linha zera drawn e myhat
myhat.draw(len(hat.contents)+1)

prob = M / (num_experiments)

``````

User Agent is: `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36`

Challenge: Scientific Computing with Python Projects - Probability Calculator

Link to the challenge:

Is this method inclusive or exclusive of the upper bound?

Hmm, it’s inclusive.

I wouldn’t reuse the variable n there.

I’m not sure this is per the instructions. You shouldn’t need to put anything back. Just return all of the contents.

Hey @JeremyLT. Thanks for your comments, not sure I follow though Since I am popping out of the original contents list (I didn’t create a copy), I need to make sure that the contents goes back to the original state after the draw. I added some coments to show what happens in the draw. (See below)

If it`s just the return bit your talking about, then yes I should change it to
return self.contents. Still can’t see how this is related to the probability

Original hat [‘blue’, ‘blue’, ‘blue’, ‘red’, ‘red’, ‘green’, ‘green’, ‘green’, ‘green’, ‘green’, ‘green’]
contents = [‘blue’, ‘blue’, ‘blue’, ‘red’, ‘red’, ‘green’, ‘green’, ‘green’, ‘green’, ‘green’] after 1 st draw
drawn = [‘green’] after 1 st draw
contents = [‘blue’, ‘blue’, ‘blue’, ‘red’, ‘green’, ‘green’, ‘green’, ‘green’, ‘green’] after 2 st draw
drawn = [‘green’, ‘red’] after 2 st draw
contents = [‘blue’, ‘blue’, ‘blue’, ‘red’, ‘green’, ‘green’, ‘green’, ‘green’] after 3 st draw
drawn = [‘green’, ‘red’, ‘green’] after 3 st draw
contents = [‘blue’, ‘blue’, ‘blue’, ‘red’, ‘green’, ‘green’, ‘green’] after 4 st draw
drawn = [‘green’, ‘red’, ‘green’, ‘green’] after 4 st draw
Original hat [‘blue’, ‘blue’, ‘blue’, ‘red’, ‘green’, ‘green’, ‘green’]
contents = [‘blue’, ‘blue’, ‘blue’, ‘red’, ‘green’, ‘green’, ‘green’, ‘green’] after returning 1 ball
drawn = [‘red’, ‘green’, ‘green’] after returning 1 ball
contents = [‘blue’, ‘blue’, ‘blue’, ‘red’, ‘green’, ‘green’, ‘green’, ‘green’, ‘red’] after returning 2 ball
drawn = [‘green’, ‘green’] after returning 2 ball
contents = [‘blue’, ‘blue’, ‘blue’, ‘red’, ‘green’, ‘green’, ‘green’, ‘green’, ‘red’, ‘green’] after returning 3 ball
drawn = [‘green’] after returning 3 ball
contents = [‘blue’, ‘blue’, ‘blue’, ‘red’, ‘green’, ‘green’, ‘green’, ‘green’, ‘red’, ‘green’, ‘green’] after returning 4 ball
drawn = after returning 4 ball

I have altered the code:

``````        for n in range(number):
r = random.randint(0,len(self.contents)-1)
self.drawn.append(self.contents.pop(r))
``````

You must create a copy. In order to prevent someone from just returning the theoretical probability, the number of experiments is somewhat low. But that means that the result is based upon repeated experiments with the balls back in their original order, which is disrupted if you ignore the advice to clone the hat.