Scientific Computing with Python Projects - Probability Calculator - contents test failure

I’m getting this error:

======================================================================
FAIL: test_hat_draw (test_module.UnitTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/runner/boilerplate-probability-calculator/test_module.py", line 20, in test_hat_draw
    self.assertEqual(actual, expected, 'Expected hat draw to reduce number of items in contents.')
AssertionError: 7 != 5 : Expected hat draw to reduce number of items in contents.

----------------------------------------------------------------------
Ran 3 tests in 0.016s

FAILED (failures=1)

I don’t really understand how to fix it. My guess is that the test is checking self.contents during the draw and noticing that nothing is being drawn. I use another variable during the draw so I don’t have to restore self.contents. This is my code:

import random

class Hat:
    def __init__(self,**kwargs):
        self.contents = []
        for key, value in kwargs.items():
            for x in range(value):
                self.contents.append(key)
    
    def draw(self, amt_to_draw):
        position = 0
        drawn_balls = []
        draw_hat = self.contents.copy() #without .copy() draw_hat is just a pointer to contents
        if amt_to_draw >= len(draw_hat):
            return draw_hat
        else:
            for x in range(amt_to_draw):
                position = random.randint(0, len(draw_hat) - 1)
                drawn_balls.append( draw_hat.pop(position) )
            return drawn_balls
        

def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
    counter = 0
    for x in range(num_experiments):
        #First a list of the balls drawn
        drawn_list = []
        drawn_list = hat.draw(num_balls_drawn)
        #Convert to the same key-value format as expected_balls
        drawn_tuple = {}
        for ball in drawn_list:
            if ball in drawn_tuple:
                drawn_tuple[ball] += 1
            else:
                drawn_tuple[ball] = 1
        #Check if drawn_tuple contains expected balls and record result
        if all(key in drawn_tuple for key in expected_balls):
            if all(expected_balls[key] <= drawn_tuple[key] for key in expected_balls):
                counter += 1
            else: continue
        else: continue
    return counter / num_experiments

I tried changing my draw function so that self.contents is also changed during the draw:

    def draw(self, amt_to_draw):
        position = 0
        drawn_balls = []
        draw_hat = self.contents.copy() #without .copy() draw_hat is just a pointer to contents
        original_hat = self.contents.copy()
        if amt_to_draw >= len(draw_hat):
            return draw_hat
        else:
            for x in range(amt_to_draw):
                position = random.randint(0, len(draw_hat) - 1)
                drawn_balls.append( draw_hat.pop(position) )
                self.contents = draw_hat.copy()
            self.contents = original_hat.copy()
            return drawn_balls

This did not do any difference. So I don’t know? It works right, it just doesn’t pass the test. Or am I wrong?

Your browser information:

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

Challenge Information:

Scientific Computing with Python Projects - Probability Calculator

It looks like you are immediately copying back the original contents. Maybe trying removing that line? The instructions also say:

This method should remove balls at random from contents and return those balls as a list of strings.

It sounds like you need to .pop() contents directly and exhaust it. Also:

The balls should not go back into the hat during the draw,

self.contents = original_hat.copy() in the draw method seems to violate this.

1 Like

Thank you! I though the test was checking self.contents content during the function, like during the loop or something.
Now I get the distinction. balls drawn from self.contents stays out of self.contents even after the return statement.

Seems kind of weird to my untrained sensibilities, but now the balls return the next time the draw function is used and I passed all the tests.

class Hat:
    def __init__(self,**kwargs):
        self.contents = []
        self.org_contents = []
        for key, value in kwargs.items():
            for x in range(value):
                self.contents.append(key)
        self.org_contents = self.contents.copy()
        
    
    def draw(self, amt_to_draw):
        position = 0
        drawn_balls = []
        self.contents = self.org_contents.copy()
        draw_hat = self.contents
        
        if amt_to_draw >= len(draw_hat):
            return draw_hat
        else:
            for x in range(amt_to_draw):
                position = random.randint(0, len(draw_hat) - 1)
                drawn_balls.append( draw_hat.pop(position) )
            return drawn_balls
1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.