Probability Calc - only getting 0.0

Tell us what’s happening:
Code is only generating a probability of 0.0

From console:
python main.py
Probability: 0.0
..F
======================================================================
FAIL: test_prob_experiment (test_module.UnitTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/runner/boilerplate-probability-calculator/test_module.py", line 27, in test_prob_experiment
    self.assertAlmostEqual(actual, expected, delta = 0.01, msg = 'Expected experiment method to return a different probability.')
AssertionError: 0.001 != 0.272 within 0.01 delta (0.271 difference) : Expected experiment method to return a different probability.


Ran 3 tests in 0.049s

FAILED (failures=1)

Your code so far

import copy
import random
# Consider using the modules imported above.

class Hat:
  def __init__(self, **kwargs):
    self.contents = []
# Assumes key is always color and value is integer, creates a list of colors mulitplied by thier frequncy listed in value. 
    for key, value in kwargs.items(): 
      self.contents += [key] * value
    
  def draw (self, num):
    if num > len(self.contents):
      return self.contents
    # Random ball selector
    balls = random.sample(copy.deepcopy(self.contents), num)
    # .remove() to use items, .pop() only works with index
    for ball in balls:
      self.contents.remove(ball)   
    return balls

def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
  #deepcopy
  hat2 = copy.deepcopy(hat)
  expected = copy.deepcopy(expected_balls)
  #num_balls is a list of the color of balls drawn
  num_balls = hat2.draw(num_balls_drawn)
  
  #calculating probability - this was the most dificult part
  for e in range(num_experiments):
    list = []
    count = 0
    # was not working because I did not use .item on expected to return the pair
    # This creates a list from the dictionary of the keys based on the value
    for k, v in expected.items():
      list += v * [k]
    #From GeeksforGeeks: all() function is an inbuilt function in Python which returns true if all the elements of a given iterable( List, Dictionary, Tuple, set, etc) are True else it returns False.
    if all(x in num_balls for x in list):
      count += 1
   
  return count / num_experiments

Your browser information:

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

Challenge: Probability Calculator

Link to the challenge:

Are you sure that this count = 0 should be inside the for loop?
count is going to be set as 0 every time the for runs.

1 Like

You are correct and more so I just realized the other variables need to be in the first for loop so they are reset with each experiment. However, now I am getting the wrong probability.

First thank you. Getting closer.

Second, thoughts?

What I am getting:

python main.py
Probability: 0.4563333333333333
..F
======================================================================
FAIL: test_prob_experiment (test_module.UnitTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/runner/boilerplate-probability-calculator/test_module.py", line 27, in test_prob_experiment
    self.assertAlmostEqual(actual, expected, delta = 0.01, msg = 'Expected experiment method to return a different probability.')
AssertionError: 0.787 != 0.272 within 0.01 delta (0.515 difference) : Expected experiment method to return a different probability.

----------------------------------------------------------------------
Ran 3 tests in 0.191s

FAILED (failures=1)
 

New code:

import copy
import random
# Consider using the modules imported above.

class Hat:
  def __init__(self, **kwargs):
    self.contents = []
# Assumes key is always color and value is integer, creates a list  of colors mulitplied by #their frequncy listed in value. 
    for key, value in kwargs.items(): 
      self.contents += [key] * value
    
  def draw (self, num):
    if num > len(self.contents):
      return self.contents
    # Random ball selector
    balls = random.sample(copy.deepcopy(self.contents), num)
    # .remove() to use items, .pop() only works with index
    for ball in balls:
      self.contents.remove(ball)   
    return balls

def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
 # moved to outside the for loops to prevent reset
  count = 0
  #calculating probability - this was the most dificult part
  for e in range(num_experiments):
    list = []
    # Variables moved into first for loop
    hat2 = copy.deepcopy(hat)
    expected = copy.deepcopy(expected_balls)
    #num_balls is a list of the color of balls drawn
    num_balls = hat2.draw(num_balls_drawn)

    # was not working because I did not use .item on expected to return the pair
    # This creates a list from the dictionary of the keys based on the value
    for k, v in expected.items():
      list += v * [k]

    #From GeeksforGeeks: all() function is an inbuilt function in Python which          
    #returns true if all the elements of a given iterable( List, Dictionary, Tuple,      
   #  set, etc)  are True else it returns False.
    if all(x in num_balls for x in list):
      count += 1
  
  #Return probability 
  return count / num_experiments

Can you print the count and num_experiments and see if they make sense?

The list, num_balls, and count all seem to make sense. From what I read the ‘all’ function should work, and seems like an ideal function. However, I also tried collections as well as .sort method, interestingly, those gave me a 0.0 match. So maybe the issue is with how I am comparing lists?

So I am confused as to how I am getting either way to high or none at all.

import collections

if collections.Counter(num_balls)==collections.Counter(list):
    count += 1
if num_balls.sort==list.sort
    count +=1

What I’m going to suggest is a very simple (brute-force) way to do it, but I think is worth trying.

How about you loop over the list like:

for e in list:
    if e:
        count += 1

In the end, you want to get the non-zeros values right?

I want to get the number of times that list has exactly the same objects as num_balls, then I am returning the percentage of the time they match, dividing it by the number in num_experiments. The lists will not always be in the same order, but must have the same objects.

For example if list contains ‘green’, ‘red’, ‘red’ ,‘blue’, then num_balls must have those exact objects in any order. So num_balls must have both of the ‘red’ objects, having only one should disqualify it.