Scientific Computing with Python Projects - Probability Calculator

Hello everybody, im working on the project “Probability Calculator” and I just can’t pass the third test. (“The experiment method should return a different probability”)
My calculations are near to what the probability of the example provided is, but not in the 0,1 range required, and i can’t figure out why.
My only guess is my 2 broad usages of pass and except, but those don’t seem to cause problems.

Here is my code on Replit: Probability Calculator - Replit

Thanks in advance!

import copy
import random


class Hat:
    contents = []

    def __init__(self, **kwargs):

        # convert input to contents
        color_dict = {}
        color_dict.update(**kwargs)

        for color in color_dict.keys():
            if color_dict.get(color) > 0:
                count = 0
                while count < color_dict.get(color):
                    count += 1
                    self.contents.append(color)

    def draw(self, drawn_balls):
        draw_number = 0
        remove_list = []

        # returning the randomly drawn balls and removing them from contents
        if drawn_balls <= len(self.contents):
            while draw_number < drawn_balls:
                draw_number += 1
                random_number = random.randrange(0, len(self.contents))
                # print("random number:" + str(random_number))
                # print(len(copy_contents))
                remove_list.append(self.contents[random_number])
                self.contents.pop(random_number)
            return remove_list


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

    run = 0
    complete_success_counter = 0

    # make copy of contents to restore original of contents (to return all the drawn balls)
    copy_contents = copy.copy(from_hat.contents)

    # return all the balls when the number of balls to draw exceeds the available quantity
    while run <= num_experiments:
        if len(from_hat.contents) < num_balls_drawn:
            # print("not enough balls left, returning all the balls")
            from_hat.contents.clear()
            for count in copy_contents:
                from_hat.contents.append(count)

        # print(len(hat.contents))

        run += 1

        drawn_balls = from_hat.draw(num_balls_drawn)
        drawn_balls_no_dupl = []

        # remove duplicates (to not check colors multiple times)
        for no_dupl in drawn_balls:
            if no_dupl not in drawn_balls_no_dupl:
                drawn_balls_no_dupl.append(no_dupl)

        # count number of balls per color
        draw_dict = {}

        for color in drawn_balls:
            try:
                draw_dict[color] = draw_dict[color] + 1
            except:
                draw_dict[color] = 1

        # print("expected balls: ")
        # print(expected_balls)
        # print(" ")
        # print("drawn balls: ")
        # print(draw_dict)
        # print("---")

        # count how many times expected and drawn balls match (per color)
        success_counter = 0

        for color in drawn_balls_no_dupl:
            try:
                if draw_dict[color] >= expected_balls[color]:
                    # print("Success: " + color)
                    success_counter += 1
            except:
                pass

        # print("---")

        # check if there is a match for all colors, and if so, add 1 to the complete success counter
        if success_counter == len(expected_balls):
            complete_success_counter += 1

    # print(complete_success_counter)

    # calculate probability and round it
    probability = round(complete_success_counter / num_experiments, 3)

    return probability

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36

Challenge Information:

Scientific Computing with Python Projects - Probability Calculator

open the browser console then run the tests, you have wrong parameter names

TypeError: experiment() got an unexpected keyword argument 'hat'

add the sample code and you will have the error in any environment that shows error (which is not yet the fcc editor)

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)

Yes, sorry, i forgot to change the variable “from_hat” back to “hat” from when i was testing. I fixed it now.
But still, the issue stays the same.

post your updated code please

I updated the code on Replit, but here it is (only class):

import copy
import random


class Hat:
    contents = []

    def __init__(self, **kwargs):

        # convert input to contents
        color_dict = {}
        color_dict.update(**kwargs)

        for color in color_dict.keys():
            if color_dict.get(color) > 0:
                count = 0
                while count < color_dict.get(color):
                    count += 1
                    self.contents.append(color)

    def draw(self, drawn_balls):
        draw_number = 0
        remove_list = []

        # returning the randomly drawn balls and removing them from contents
        if drawn_balls <= len(self.contents):
            while draw_number < drawn_balls:
                draw_number += 1
                random_number = random.randrange(0, len(self.contents))
                # print("random number:" + str(random_number))
                # print(len(copy_contents))
                remove_list.append(self.contents[random_number])
                self.contents.pop(random_number)
            return remove_list


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

    run = 0
    complete_success_counter = 0

    # make copy of contents to restore original of contents (to return all the drawn balls)
    copy_contents = copy.copy(hat.contents)

    # return all the balls when the number of balls to draw exceeds the available quantity
    while run <= num_experiments:
        if len(hat.contents) < num_balls_drawn:
            # print("not enough balls left, returning all the balls")
            hat.contents.clear()
            for count in copy_contents:
                hat.contents.append(count)

        # print(len(hat.contents))

        run += 1

        drawn_balls = hat.draw(num_balls_drawn)
        drawn_balls_no_dupl = []

        # remove duplicates (to not check colors multiple times)
        for no_dupl in drawn_balls:
            if no_dupl not in drawn_balls_no_dupl:
                drawn_balls_no_dupl.append(no_dupl)

        # count number of balls per color
        draw_dict = {}

        for color in drawn_balls:
            try:
                draw_dict[color] = draw_dict[color] + 1
            except:
                draw_dict[color] = 1

        # print("expected balls: ")
        # print(expected_balls)
        # print(" ")
        # print("drawn balls: ")
        # print(draw_dict)
        # print("---")

        # count how many times expected and drawn balls match (per color)
        success_counter = 0

        for color in drawn_balls_no_dupl:
            try:
                if draw_dict[color] >= expected_balls[color]:
                    # print("Success: " + color)
                    success_counter += 1
            except:
                pass

        # print("---")

        # check if there is a match for all colors, and if so, add 1 to the complete success counter
        if success_counter == len(expected_balls):
            complete_success_counter += 1

    # print(complete_success_counter)

    # calculate probability and round it
    probability = round(complete_success_counter / num_experiments, 3)

    return probability

There is an issue with the tests of this project, the resolution is not live yet but it will be soon. You are also failing this extra test:

Failed:The draw method should behave correctly when the number of ballsto extract is bigger than the number of balls in the hat.

Your function doesn’t work correctly when the balls to extract are more than the content of the hat

pyodide.asm.js:9 Traceback (most recent call last):
pyodide.asm.js:9   File "/home/pyodide/test_module.py", line 15, in test_hat_draw_2
pyodide.asm.js:9     self.assertEqual(actual, expected, 'Expected hat draw to return all items from hat contents.')
pyodide.asm.js:9 AssertionError: None != ['yellow', 'yellow', 'yellow', 'yellow', [118 chars]est'] : Expected hat draw to return all items from hat contents.

Because the I already addressed the assignment “If the number of balls to draw exceeds the available quantity, return all the balls.” in line 45-51 of my previous code, I believe you’re talking about when “num_balls_drawn” in the call for the function experiment (e.g. print(experiment(hat=hat,
expected_balls={“red”: 2, “green”: 1},
num_balls_drawn=100000000,
num_experiments=2000))) is higher than the contents of the hat?

If so, i fixed this in the following code: (line 39-41)

import copy
import random


class Hat:
    contents = []

    def __init__(self, **kwargs):

        # convert input to contents
        color_dict = {}
        color_dict.update(**kwargs)

        for color in color_dict.keys():
            if color_dict.get(color) > 0:
                count = 0
                while count < color_dict.get(color):
                    count += 1
                    self.contents.append(color)

    def draw(self, drawn_balls):
        draw_number = 0
        remove_list = []

        # returning the randomly drawn balls and removing them from contents
        if drawn_balls <= len(self.contents):
            while draw_number < drawn_balls:
                draw_number += 1
                random_number = random.randrange(0, len(self.contents))
                # print("random number:" + str(random_number))
                # print(len(copy_contents))
                remove_list.append(self.contents[random_number])
                self.contents.pop(random_number)
            return remove_list


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

    if num_balls_drawn > len(hat.contents):
        print("Number of balls to draw is too high.")
        exit()

    run = 0
    complete_success_counter = 0

    # make copy of contents to restore original of contents (to return all the drawn balls)
    copy_contents = copy.copy(hat.contents)

    # return all the balls when the number of balls to draw exceeds the available quantity
    while run <= num_experiments:
        if len(hat.contents) < num_balls_drawn:
            # print("not enough balls left, returning all the balls")
            hat.contents.clear()
            for count in copy_contents:
                hat.contents.append(count)

        # print(len(hat.contents))

        run += 1

        drawn_balls = hat.draw(num_balls_drawn)
        drawn_balls_no_dupl = []

        # remove duplicates (to not check colors multiple times)
        for no_dupl in drawn_balls:
            if no_dupl not in drawn_balls_no_dupl:
                drawn_balls_no_dupl.append(no_dupl)

        # count number of balls per color
        draw_dict = {}

        for color in drawn_balls:
            try:
                draw_dict[color] = draw_dict[color] + 1
            except:
                draw_dict[color] = 1

        # print("expected balls: ")
        # print(expected_balls)
        # print(" ")
        # print("drawn balls: ")
        # print(draw_dict)
        # print("---")

        # count how many times expected and drawn balls match (per color)
        success_counter = 0

        for color in drawn_balls_no_dupl:
            try:
                if draw_dict[color] >= expected_balls[color]:
                    # print("Success: " + color)
                    success_counter += 1
            except:
                pass

        # print("---")

        # check if there is a match for all colors, and if so, add 1 to the complete success counter
        if success_counter == len(expected_balls):
            complete_success_counter += 1

    # print(complete_success_counter)

    # calculate probability and round it
    probability = round(complete_success_counter / num_experiments, 3)

    return probability

Is this what you meant?

Thanks in advance!

it’s still failing:
image

You are not satisfying this:

If the number of balls to draw exceeds the available quantity, return all the balls.

The test is finding None instead of the expected list.

(This is the development version of freeCodeCamp, it will be live soon)

I have updated the code, so that now the draw function itself reacts accordingly to too many balls being drawn. The test is still failing, and I have absolutely no idea why. If possible, could you look over the code and maybe tell me where my problem is? I’m out of ideas.

Thank you in advance!

import copy
import random


class Hat:
    contents = []
    copy_contents = []

    def __init__(self, **kwargs):

        # convert input to contents
        color_dict = {}
        color_dict.update(**kwargs)

        for color in color_dict.keys():
            if color_dict.get(color) > 0:
                count = 0
                while count < color_dict.get(color):
                    count += 1
                    self.contents.append(color)

        # make copy of contents to restore original of contents (to return all the drawn balls)
        cc = copy.deepcopy(self.contents)
        self.copy_contents = cc

    def draw(self, drawn_balls):


        if len(self.contents) < drawn_balls:
            # print("not enough balls left, returning all the balls")
            self.contents.clear()
            for count in self.copy_contents:
                self.contents.append(count)

            if len(self.contents) < drawn_balls:
                print("Too many balls drawn")
                exit()

        # print("COPY:")
        # print(hat.copy_contents)
        # print("OG:")
        # print(hat.contents)

        draw_number = 0
        remove_list = []

        # returning the randomly drawn balls and removing them from contents
        if drawn_balls <= len(self.contents):
            while draw_number < drawn_balls:
                draw_number += 1
                random_number = random.randrange(0, len(self.contents))
                # print("random number:" + str(random_number))
                # print(len(copy_contents))
                remove_list.append(self.contents[random_number])
                self.contents.pop(random_number)

            return remove_list


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

    run = 0
    complete_success_counter = 0

    # return all the balls when the number of balls to draw exceeds the available quantity
    while run <= num_experiments:

        run += 1

        drawn_balls = hat.draw(num_balls_drawn)
        drawn_balls_no_dupl = []

        # remove duplicates (to not check colors multiple times)
        for no_dupl in drawn_balls:
            if no_dupl not in drawn_balls_no_dupl:
                drawn_balls_no_dupl.append(no_dupl)

        # count number of balls per color
        draw_dict = {}

        for color in drawn_balls:
            try:
                draw_dict[color] = draw_dict[color] + 1
            except:
                draw_dict[color] = 1

        # print("expected balls: ")
        # print(expected_balls)
        # print(" ")
        # print("drawn balls: ")
        # print(draw_dict)
        # print("---")

        # count how many times expected and drawn balls match (per color)
        success_counter = 0

        for color in drawn_balls_no_dupl:
            try:
                if draw_dict[color] >= expected_balls[color]:
                    # print("Success: " + color)
                    success_counter += 1
            except:
                pass

        # print("---")

        # check if there is a match for all colors, and if so, add 1 to the complete success counter
        if success_counter == len(expected_balls):
            complete_success_counter += 1

    # print(complete_success_counter)

    # calculate probability and round it
    probability = round(complete_success_counter / num_experiments, 3)

    return probability```

now the fourth test I was talking about is live

image

what does your draw return in a situation like this?

hat = Hat(black=6, red=4, green=3)
hat.draw(20)

because all I see is an error

This is what is being returned:
image

If the number of balls to draw exceeds the available balls, just like in your example, this string is being printed and the program exits.
That is exactly what i programmed it to do in line 35-37.
I don’t get an error.

How is that satisfying this?

If the number of balls to draw exceeds the available quantity, return all the balls.

Okay I misinterpreted the it. I’ve updated the code (line 47-51), and it works like intended, but I’m still failing the test, and I don’t know why.
Here’s the updated code:

import copy
import random


class Hat:
    contents = []
    copy_contents = []

    def __init__(self, **kwargs):

        # convert input to contents
        color_dict = {}
        color_dict.update(**kwargs)

        for color in color_dict.keys():
            if color_dict.get(color) > 0:
                count = 0
                while count < color_dict.get(color):
                    count += 1
                    self.contents.append(color)

        # make copy of contents to restore original of contents (to return all the drawn balls)
        cc = copy.deepcopy(self.contents)
        self.copy_contents = cc

    def draw(self, drawn_balls):

        # print("COPY:")
        # print(hat.copy_contents)
        # print("OG:")
        # print(hat.contents)

        draw_number = 0
        remove_list = []

        # returning the randomly drawn balls and removing them from contents
        while draw_number < drawn_balls:
            # print(self.contents)
            # print(len(remove_list))
            draw_number += 1
            random_number = random.randrange(0, len(self.contents))
            # print("random number:" + str(random_number))
            # print(len(copy_contents))
            remove_list.append(self.contents[random_number])
            self.contents.pop(random_number)

            if len(self.contents) < 1:
                # print("not enough balls left, returning all the balls")
                self.contents.clear()
                for count in self.copy_contents:
                    self.contents.append(count)

        return remove_list


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

    run = 0
    complete_success_counter = 0

    # return all the balls when the number of balls to draw exceeds the available quantity
    while run <= num_experiments:

        run += 1

        drawn_balls = hat.draw(num_balls_drawn)
        drawn_balls_no_dupl = []

        # remove duplicates (to not check colors multiple times)
        for no_dupl in drawn_balls:
            if no_dupl not in drawn_balls_no_dupl:
                drawn_balls_no_dupl.append(no_dupl)

        # count number of balls per color
        draw_dict = {}

        for color in drawn_balls:
            try:
                draw_dict[color] = draw_dict[color] + 1
            except:
                draw_dict[color] = 1

        # print("expected balls: ")
        # print(expected_balls)
        # print(" ")
        # print("drawn balls: ")
        # print(draw_dict)
        # print("---")

        # count how many times expected and drawn balls match (per color)
        success_counter = 0

        for color in drawn_balls_no_dupl:
            try:
                if draw_dict[color] >= expected_balls[color]:
                    # print("Success: " + color)
                    success_counter += 1
            except:
                pass

        # print("---")

        # check if there is a match for all colors, and if so, add 1 to the complete success counter
        if success_counter == len(expected_balls):
            complete_success_counter += 1

    # print(complete_success_counter)

    # calculate probability and round it
    probability = round(complete_success_counter / num_experiments, 3)

    return probability```

keep looking at the test output on your own
image

When there are more balls to draw than available balls you need to return the content of the hat as is, do not change the order