Build a Probability Calculator Project - method picking up data outside of class?

Hi all,

I am attempting to complete the probability calculator project. Test output for printing probability variable below should be around 0.356. My current function produces around 0.7 which is twice that.

I am thinking it is something wrong with the draw method in the Hat class but I cant make it out.

What I have noticed is that when I comment out the probability/get experiment function and print inside the for loop in the draw method, I print the n in range balls_drawn.

If i add probability/get experiment back, and then print inside the for loop in the draw method, the print seems to produce more than the n times expected.

import copy
import random

class Hat:
    def __init__(self, **kwargs):
        self.contents = []
        self.removed = []
        for k, v in kwargs.items():
            k = [k] * v
            self.contents.extend(k)
        
    def __str__(self):
        return str(self.contents)

    def draw(self, balls_drawn):
        if balls_drawn < len(self.contents):
            for n in range(balls_drawn):
                self.removed += [self.contents.pop(random.randrange(len(self.contents)))]             
            return self.removed
        self.removed = copy.copy(self.contents)
        self.contents.clear()
        return self.removed        
        
def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
    M = 0
    probdrawn = []


    for k,v in expected_balls.items():
        k = [k] *v
        probdrawn.extend(k)

    for e in range(num_experiments):
        test_hat = copy.deepcopy(hat)
        a = probdrawn
        b = test_hat.draw(num_balls_drawn)
        if all(balls in b for balls in a) == True:
            M += 1
        probability = M / num_experiments
    return probability

hat = Hat(black=6, red=4, green=3)
probability = experiment(hat=hat,
                  expected_balls={"red":2,"green":1},
                  num_balls_drawn=5,
                  num_experiments=2000)

Your problem lies here: all(balls in b for balls in a)
Assume

a = ['red', 'red', 'green']
b = ['black', 'green', 'black', 'black', 'red']`

first ball: 'red' in b # True
second ball: 'red' in b # True
third ball: 'green' in b #True

The result is of all() is True but you have only one 'red' inside b. Therefore, you are overestimating the probability.

When I was testing the all function, it looks like it returns false if it is not included twice.

Here is my test lists. The print below returns false because red isnt on there twice.

list1 = ['red','red,','green']
list2 = ['red','green','blue','yellow']
print(all(items in list2 for items in list1))

I’m sorry but you tested it with a typo. You have 'red,' as the second item.

For this case you need to structure the check in a different way.

1 Like

I updated my check. Looks to be working correctly now. Am unsure as to why I am not passing the last test. My probability is near the expected output

https://www.freecodecamp.org/learn/scientific-computing-with-python/build-a-probability-calculator-project/build-a-probability-calculator-project

import copy
import random

class Hat:
    def __init__(self, **kwargs):
        self.contents = []
        self.removed = []
        for k, v in kwargs.items():
            k = [k] * v
            self.contents.extend(k)

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

    def draw(self, balls_drawn):
        if balls_drawn < len(self.contents):
            for n in range(balls_drawn):
                self.removed += [self.contents.pop(random.randrange(len(self.contents)))]
            return self.removed
        self.removed = copy.copy(self.contents)
        self.contents.clear()
        return self.removed   

def compare_lists(list1, list2):
    for item in set(list1):
        if list1.count(item) > list2.count(item):
            return False
    return True     
        
def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
    M = 0
    probdrawn = []

    for k,v in expected_balls.items():
        k = [k] *v
        probdrawn.extend(k)

    for n in range(num_experiments):
        test_hat = copy.deepcopy(hat)
        a = probdrawn
        b = test_hat.draw(num_balls_drawn)
        if compare_lists(a,b):
            M += 1
        probability = M / num_experiments
    print(probability)

hat = Hat(black=6, red=4, green=3)
probability = experiment(hat=hat,
                  expected_balls={"red":2,"green":1},
                  num_balls_drawn=5,
                  num_experiments=2000)

            




i had to update my experiment to return probability instead of print. thank you for the help

I’m glad you solved it!

1 Like