# Build a Probability Calculator Project - Build a Probability Calculator Project

### Tell us what’s happening:

I am having a hard time understanding the instructions.
" The balls should not go back into the hat during the draw
If the number of balls to draw exceeds the available quantity, return all the balls."
Example Hat(black = 6, red = 4, green = 3)
expected_balls={‘red’: 2, ‘green’: 1} ,
num_balls_drawn=5,
num_experiments=20)
the number of ball to draw is 5, Then the function will return a list 5 items until the list has less than 5 items. Then the remainder of the list is always returned. The original list is 13. After removing 5 per drawing , the remaining calls will return a list of 3 items.
So how can you ever expect the function to return 3 items ({‘red’: 2, ‘green’: 1} ?
The other question is that the removal is random. Yet the test is expecting the same result {red, blue} ? how is this random?

``````import copy
import random

class Hat():

def draw(self, number_of_balls):
#If the number of balls to draw exceeds the available quantity, return all the balls.

if number_of_balls > len(self.contents):
return self.contents
returned_balls = []
contents = self.contents #.copy()
#iterate to remove the number of balls
i = number_of_balls

while i:
index = random.randint(0, len(self.contents))
#print(f'find {index} remove: {contents}')
if len(self.contents) > index :
#print(f'find {index} remove: {self.contents[index]}')

item = self.contents[index]
print(f'find {index}  remove: {item}')
returned_balls.append(item )
self.contents.remove(item)
i -= 1

#else:
print (f'returned: {returned_balls}   contents: {self.contents}')
return returned_balls

def __init__(self,**args):
#if your hat is {'red': 2, 'blue': 1}, contents should be ['red', 'red', 'blue']
self.args = args
self.contents =[]
for x,y in args.items():
for i in range(y):
self.contents.append(x)

def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
n = 0
m = int(num_experiments)
print(f'start {hat.args} expected: {expected_balls}, num: {num_balls_drawn}, iterations:{num_experiments}')

for _ in range(m):
ret_list = hat.draw(num_balls_drawn)
#ret_balls = list of balls
returned_dict = {x:ret_list.count(x) for x in ret_list}

shared_items = {k: returned_dict[k] for k in returned_dict \
if k in expected_balls and returned_dict[k] == expected_balls[k]}
#print(f' shared {len(shared_items)} contents: {hat.contents}')

if  len(shared_items) :
print(f' {len(shared_items)} shared: {shared_items}')
if len(shared_items) == len(expected_balls):
n += 1
if  n:
return m / n
return 0

#for x,y in expected_balls.items():
#       for i in range(y):
#E           expected_ball_list.append(x)
#[x for x in a if x in b]
#list(set(a).intersection(set(b)))
#                new_list = []
#for element in a:
#    if element in b:
#       new_list.append(element)
# expected_balls = dictionary {'red':2,'green':1}
#des the list containt 2 occurances of 'red' and 1 occence of green

#hat = Hat(red=5, orange=4, black=1, blue=0, pink=2, striped=9)
hat = Hat(black=6, red=4, green=3)
probability = experiment(hat=hat,
expected_balls={'red':2,'green':1},
num_balls_drawn=5,
num_experiments=20)
print(probability)

``````

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

### Challenge Information:

Build a Probability Calculator Project - Build a Probability Calculator Project

Sorry the example should be list with items not eq. 13.
Second the random is returning a number from 0 to the len(list). Is that the random function (randominit) when referring to not including the seed?

The tests set the random number generator behavior so they always expect the same results

3 is less than 5, so you can check if those 3 balls are between the 5 extracted

you start with the full hat, extract 5 balls, check if the balls match
then the next extraction is with a new hat, not with the same hat

Were in the instructions does it state how to create multiple new hats?
states:

[quote=“ilenia, post:4, topic:709218”]

• `hat`: A hat object containing balls that should be copied inside the function.
• [/quote]
• [quote=“ilenia, post:4, topic:709218”]
• The balls should not go back into the hat during the draw, similar to an urn experiment without replacement. If the number of balls to draw exceeds the available quantity, return all the balls.
• [/quote]
• Th instruction infers that the experiment calls the same hat object, reducing the contents by the number of balls. As to when the number of items in the content list is less than the number of balls to extract. Otherwise using new hats the content will never shrink.
*Do not see where it states to create a new hat with the remaining context nor create an array of hats.
The comment left is more confusing.

Here

Each experiment consists of starting with a hat containing the specified balls,

Here it says that each time you do an experiment you start with a new hat. Well, it say with an hat containing the specified balls, but considering your draw method should remove balls from the hat, and you should not implement a way to restore the balls, you need a new hat

still confused.

I’m passing the new hat object to the method experiment. The call : probability = experiment(hat.
So each time the experiment method called with a new hat object.
I’m iterating, calling hat.draw by the num_experiments. Each call draws down the contents by the number of balls.
So I pass a hat having {‘black’: 6, ‘red’: 4, ‘green’: 3} = 13 with the number of balls = 5., 20 iterations
iteration 1 context 8 (13 - 5)
iteration 2 context 3 (8-5)
iteration 3 - 20 content 3.
The remaining iterations remain 3 as the number of balls 5 > 3. Unless the contents are a multiple of number of balls the contents will never drawn to 0.

`hat` : A hat object containing balls that should be **copied inside the function.** On the other hand if create a copy of the hat to avoid changing the original. Such that each iteration starts are 13 (as example above) . Then the contents of object hat never change (only work on the copy) and are never drawn down. By using a copy on each iteration I'm by default restoring the balls to the original list. Here it says that **each time you do an experiment you start with a new hat.** Well, it say with an hat containing the specified balls, but considering your draw method should remove balls from the hat, and you should not implement a way to restore the balls, **you need a new hat** This is the confusing part. If I treat each iteration of draw as an experiment, using a copy of hat object. Each draw uses a copy of the original, the the contents are drawn down once. The balls can never be restored or completely drawn down unless the number of ball = length of content. In that case I should not be generating: **The `draw` method should behave correctly when the number of balls to extract is bigger than the number of balls in the hat.** AssertionError: 19 != 0 : Expected hat draw to leave no items in contents.

bad formatting sorry! I do appreciate the fee back.
first part in response to JeremyLT

second to ilenia

`hat` : A hat object containing balls that should be copied inside the function.

On the other hand if create a copy of the hat to avoid changing the original. Such that each iteration starts are 13 (as example above) .
Then the contents of object hat never change (only work on the copy) and are never drawn down.
By using a copy on each iteration I’m by default restoring the balls to the original list. Here it says that

each time you do an experiment you start with a new hat.

Well, it say

with an hat containing the specified balls, but considering your draw method should remove balls from the hat, and you should not implement a way to restore the balls,

you need a new hat

This is the confusing part. If I treat each iteration of draw as an experiment, using a copy of hat object. Using a new copy of hat object considered a new hat?
Each draw uses a copy of the original, the the contents are drawn down once.
The balls can never be restored or completely drawn down unless the number of ball = length of content. In that case I should not be generating: *

The `draw` method should behave correctly when the number of balls to extract is bigger than the number of balls in the hat.*

AssertionError: 19 != 0 : Expected hat draw to leave no items in contents.

no, this should not happen

first experiment:

• hat with 13 balls, extract 5, check if between those fives you have the required ones

second exepriemnt:

• new hat with 13 balls, extract 5, check

If you extract more balls than there are in the hat, hat.contents at the end should be empty, here the tests find that the hat is not empty