Probability calculator, second test

General

Jun 12

1 / 1

Jun 12

8m ago

Beatrix

8m

Hello everyone, I am currently doing the probability calculator challenge and cannot pass the second and third tests. Whilst I already have an idea of what is wrong in my code for the third test after reading posts from other people, I still am not sure why I am failing the second test, and any help would be appreciated. Many thanks!
Here is my code and below I have copied the text displayed by the failed second unit test:

``````""" This is a probability calculator. It has a Hat class that takes a number of arguments that
specify the number of balls of each colour that are in the hat, and a draw method that randomly
draws a number of balls WITHOUT REPLACEMENT.
There is then an experiment class that returns the probability of drawing balls of a  specific colour
if we repeat the experiment a specified number of times"""

import random
import copy

class Hat:

""" This clas defines the Hat for whoch balls can be placed in, and a method to draw them """

def __init__(self, **kwargs):
self.hat = kwargs
self.contents = []
ball_colour_freq = kwargs.values()
self.total_balls = sum(ball_colour_freq)
for key, value in kwargs.items():
for i in range(value):
self.contents.append(key)

def draw(self, balls_to_be_drawn):

""" This is function that randomly draws a specified number of balls
(called balls_to_be_drawn) from the hat."""

self.balls_to_be_drawn = balls_to_be_drawn
drawn = dict.fromkeys(self.hat.keys(), 0)
for i in range(balls_to_be_drawn):
# drawing a random ball
ball_drawn = random.choice(list(self.hat))
self.hat[ball_drawn] = - 1
drawn[ball_drawn] = + 1
drew = list(drawn.keys())
return drew

def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
#must usee copy hat in here
""" a function that returns the probability of drawing certain types of balls over
n experiments"""

match = 0
balls_drawn_in_experiment_set = set(hat.draw(num_balls_drawn))
expected_balls_set = set(expected_balls.keys())
expected_balls_set = set(expected_balls.keys())
for i in range(num_experiments):
copy.deepcopy(hat)
if set(balls_drawn_in_experiment_set).intersection(set(expected_balls_set)) != 0:
match = + 1

copy.deepcopy(hat)
probability = match / num_experiments
return probability

``````

Traceback (most recent call last):
File “/home/runner/boilerplate-probability-calculator-5/test_module.py”, line 16, in test_hat_draw
self.assertEqual(actual, expected, ‘Expected hat draw to return two random items from hat contents.’)
AssertionError: Lists differ: [‘red’, ‘blue’] != [‘blue’, ‘red’]

First differing element 0:
‘red’
‘blue’

• [‘red’, ‘blue’]

• [‘blue’, ‘red’] : Expected hat draw to return two random items from hat contents.

In your `__init__()`, you have the hat contents stored as a list in `contents` and a dict in `hat` and you use `hat` in your `draw()` method. Then to draw, you are doing

I don’t think you mean to assign `-1` and `+1` here; it looks like you mean to decrement/increment. Regardless, you are now using a list version of `hat` when you have that already, in `self.contents`. Use `random.choice()` on `self.contents`, remove the ball from there, and add it to `drew`. I’m not sure that selecting from a dict turned into a list will yield the expected results for the test anyway. It might, but I didn’t test it since you already have a list available.

Your probability is low because you are not copying the hat correctly in the experiment. Have a quick look at the python docs for the copy module and you’ll see why.

Also, your `draw()` method allows you to draw more balls than are available in the hat, so you will need to fix that too to pass all the experiment tests.

thank you, I modified the code to follow the first part of your advice. Here it is now, and it passes the second test, so i think i will leave it at that.
I will definitely look into using the copy method better.

`````` def draw(self, balls_to_be_drawn):

""" This is a function that randomly draws a specified number of balls
(called balls_to_be_drawn) out of the hat."""
drew_balls = list()
self.balls_to_be_drawn = balls_to_be_drawn
for i in range(balls_to_be_drawn):
# drawing a random ball
ball_drawn = random.choice(list(self.contents))
self.contents.remove(ball_drawn)
drew_balls.append(ball_drawn)
drew_balls.sort()
return drew_balls
``````

I am not sure I understand the last part of your advice… Because the number of balls that need to be drawn (num_balls_drawn) out of the hat at for each draw will always be smaller than the number of balls present in the hat.

So provided that the hat is refilled at the end of each iteration of the experiment ( i still need to figure out where to put the deepcopy method to achieve that), the balls in the hat will never run out and be less than the number of balls that need to be drawn, right?

Nope. The second part of the `test_prob_experiment()` test tests this explicitly. It creates a hat with 19 balls and draws 20.

`copy.deepcopy()` returns a copy. You’re calling it without assigning the return value to anything. So you’re making a copy but not using it.

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