Hello guys, I have been working on the Prob. Calculator for the past weeks (stopped to enjoy christmas and jumped back into it today) and I had some issues with replit (Some questions on the forum helped me advance a little bit, but I’m still getting issues with the final test.
Thanks in advance for your replies.
Here’s the error message:
======================================================================
FAIL: test_prob_experiment (test_module.UnitTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/runner/boilerplate-probability-calculator-1/test_module.py", line 27, in test_prob_experiment
self.assertAlmostEqual(actual, expected, delta = 0.01, msg = 'Expected experiment method to return a different probability.')
AssertionError: 1.0 != 0.272 within 0.01 delta (0.728 difference) : Expected experiment method to return a different probability.
----------------------------------------------------------------------
Ran 3 tests in 0.003s
FAILED (failures=1)
And here’s my code:
import copy
import random
class Hat:
def __init__(self, **kwargs):
self.contents = []
self.total_number_balls = sum( kwargs.values())
self.list_keys = list(kwargs.keys())
self.dict = dict(kwargs)
for keys in kwargs:
num_balls = kwargs[keys]
colour_name = keys
for balls in range(num_balls):
self.contents.append(colour_name)
def draw (self,num_balls):
#_______Remove balls at random from the hat
Total_quantity = self.total_number_balls
content_copy = self.contents.copy()
content_copy_length = len(content_copy)
random_balls_list = []
for draws in range(num_balls):
ball_drawn = random.choice(content_copy)
random_balls_list.append(ball_drawn)
self.contents.remove(ball_drawn)
if num_balls > content_copy_length:
self.contents.append(ball_drawn)
return random_balls_list
def experiment (hat,num_balls_drawn,num_experiments,expected_balls):
# def experiment (hat=None,num_balls_drawn=None,num_experiments=None,expected_balls=None):
event = 0
total_trials =0
for trials in range(num_experiments):
for keys,values in hat.dict.items():
for keys2,values2 in expected_balls.items():
if keys ==keys2 and values >= values2:
total_trials +=1
if total_trials >= len(expected_balls):
total_trials = 0
event += 1
else:
total_trials = 0
return event / num_experiments
1 Like
I don’t see where you’re drawing balls from the hat for the experiment. It appears that you are comparing the initial set of balls with a subset that should be drawn, which should always succeed unless you are looking for balls not present in the original set. Since your probability is 1, that means every trial is a success, which is wrong in most cases. For your experiment code, the easiest way to debug is to log the expected balls, the drawn balls, and whether the draw was successful or not and find the misclassified experiments.
Second, I’m not sure your draw()
method is coded according to the spec since it does not appear to handle the cases of drawing all balls or more balls than are present correctly.
1 Like
I changed my code according to your suggestions and I feel closer now. Here is the error message:
FAIL: test_prob_experiment (test_module.UnitTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/runner/boilerplate-probability-calculator-1/test_module.py", line 27, in test_prob_experiment
self.assertAlmostEqual(actual, expected, delta = 0.01, msg = 'Expected experiment method to return a different probability.')
AssertionError: 0.126 != 0.272 within 0.01 delta (0.14600000000000002 difference) : Expected experiment method to return a different probability.
----------------------------------------------------------------------
Ran 3 tests in 0.017s
FAILED (failures=1)
And here’s my code:
import copy
import random
class Hat:
def __init__(self, **kwargs):
self.contents = []
self.total_number_balls = sum( kwargs.values())
self.list_keys = list(kwargs.keys())
self.dict = dict(kwargs)
for keys in kwargs:
num_balls = kwargs[keys]
colour_name = keys
for balls in range(num_balls):
self.contents.append(colour_name)
def draw (self,num_balls):
#_______Remove balls at random from the hat
content_copy = self.contents.copy()
random_balls_list = []
ball_drawn = ''
for draws in range(num_balls):
if num_balls < len(self.contents):
ball_drawn = random.choice(self.contents)
random_balls_list.append(ball_drawn)
self.contents.remove(ball_drawn)
else:
self.contents = content_copy
return random_balls_list
def experiment (hat,num_balls_drawn,num_experiments,expected_balls):
# def experiment (hat=None,num_balls_drawn=None,num_experiments=None,expected_balls=None):
event = 0
total_trials =0
draws = []
sum_expected_values = sum(expected_balls.values())
for trials in range(num_experiments):
draws= hat.draw(num_balls=num_balls_drawn)
for keys in draws:
values = draws.count(keys)
for expected_keys,expected_values in expected_balls.items():
if keys == expected_keys and values >= expected_values:
total_trials +=1
if total_trials >= sum_expected_values:
event += 1
total_trials = 0
else:
total_trials = 0
return event / num_experiments```
The draw
method is not drawing balls from content_copy
unless all or more of the balls are requested and I don’t see where any copies of the hat are being made elsewhere when you run out of balls. Since your probability is low, you need to log the results of your experiment with the success or failure, the balls drawn, and the expected balls to find the trials that are misclassified as failures instead of successes.
Hi Jeremy, happy new year!
I have been working on the project and I starting to realize that I don’t think I understand the challenge properly. I did the changes to the draw method and here is the message:
probability = prob_calculator.experiment(
File "/home/runner/boilerplate-probability-calculator-1/prob_calculator.py", line 65, in experiment
draws= hat.draw(num_balls=num_balls_drawn)
File "/home/runner/boilerplate-probability-calculator-1/prob_calculator.py", line 25, in draw
self.contents.remove(ball_drawn)
ValueError: list.remove(x): x not in list
exit status 1
And here’s my code (just the draw function):
def draw (self,num_balls):
#_______Remove balls at random from the hat
content_copy = self.contents.copy()
random_balls_list = []
for draws in range(num_balls):
ball_drawn = random.choice(self.contents)
self.contents.remove(ball_drawn)
random_balls_list.append(ball_drawn)
if num_balls > len(content_copy):
self.contents = content_copy
return random_balls_list
I did as you said and tried logging the results, and I think that maybe the reason why my results are getting either low or high (one got 0.627) are because (like you said) the draw function isn’t working.
I get it everytime it loops the code removes one ball from the self.contents list. However shouldn’t the code loop as many time as the number of balls in the argument?
You also mentioned I should have a copy of the Hat in case the original gets empty, I haven’t figured it out yet the best way to use it.
I think you’re just making it too difficult. The spec says to return all the balls in the hat if all or more are requested. You can do that without looping, but it really shouldn’t be in the loop. If not, then you draw randomly, like your loop.
The problem with copying is that it’s harder to do in the draw method (not to mention it’s a side effect that’s not really part of what would usually be considered drawing balls from hats) as opposed to creating a copy of the original hat on each experiment.