Probability Calc - I think my math is wrong, and need some help

So, I’m getting no error codes, and I get “fairly” close (depending, I’ve redone my code about a thousand times… looking through the forums at others code to see what they’ve done to maybe fix my code while not cheating- to no avail). I don’t think it’s my code, at this point, I think it’s my math and understanding of the urn problem - or lack there of.

Below is my code and any help would be awesome =/ Yes I know I recopied my Draw function in the “experiment”. It works inside the Hat Class itself, but when I use it outside, it will return a bunch of "None"s… which is weird, so I copied the logic inside the “experiment”. Good, → no. Functional… well, maybe =/

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

class Hat:
    def __str__(self):
        totalBalls = ""
        for key, value in self.allBalls.items():
            totalBalls = totalBalls + "{}".format((key+ " ")*value)
        return(totalBalls)
        #whoops... Didn't need this
        #Habit from the other one
        
            
    # The class should take a variable number of arguments 
    # tHat specify the number of balls of each color tHat are in the Hat.
    def __init__(self, **allBalls):
        self.allBalls = allBalls
        self.contents = list()
        for key, value in self.allBalls.items():
            i = value
            while i > 0:
                self.contents.append(key)
                i = i-1

    # A Hat will always be created with at least one ball. 
    # The arguments passed into the Hat object 
    # upon creation should be converted to a contents instance variable
        self.colorOfBalls = list()
        self.numberOfBalls = list()
        for key, value in allBalls.items():
            self.colorOfBalls.append(key)
            self.numberOfBalls.append(value)


    def ballList(self):
        newList = list()
        for key, value in self.allBalls.items():
            i = value
            while i > 0:
                newList.append(key)
                i = i-1
        return(newList)

    def numbers(self):
        return(self.numberOfBalls)

    # The Hat class should have a draw method 
    # tHat accepts an argument indicating the number of balls to draw from the Hat. 
    # This method should remove balls at random from contents 
    # and return those balls as a list of strings. 
    # 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.
    def draw(self, drawNumber=0):
        #self.contents = copy.deepcopy(self.contents)
        drawList = list()
        i = 0
        if drawNumber >= (len(self.contents)):
            # call ballList function
            self.contents.extend(self.ballList())
            #print(drawNumber, " + ",  len(self.contents))
            #print(self.contents)
        else:
            while i < drawNumber:
                randBallNumber = random.randint(0, len(self.contents)-1)
                #print(randBallNumber)
                drawList.append(self.contents[randBallNumber])
                self.contents.remove(self.contents[randBallNumber])
                #print(drawList)
                #print(self.contents)
                i = i+1
            #print(drawList)
            if drawList == None:
                self.contents.extend(self.ballList())
                #print(drawList)
            else:
                #print(drawList)
                return(drawList)




def experiment(hat, expected_balls={}, num_balls_drawn=0, num_experiments=0):
 # Perform "N" experiments (num_experiments), count how many times ("M") we get
 # at least 2 red balls and 1 green ball. Divide the probability as M/N ->return this<-

 # Each experiment starts with a Hat(Hat), drawing a number of balls(draw function from Hat.draw), 
 # and check to see if we got got the balls we were attempting to draw (if statement?)
    _tempHat_contents = copy.deepcopy(hat.contents)
    
    counter = 0
    for x in range(num_experiments):
        multipleBalls = list()
        i = 0
        for key, value in expected_balls.items():
            i = value
            while i > 0:
                multipleBalls.append(key)
                i = i-1
        # ++>DELETE<++ data = ^^^ also --> expected_balls


        #print(hat.draw(5))
        ballDraw = list()
        q = 0
        #countUp = 1
        while q < num_balls_drawn:
            #print(random.randint(0, len(_tempHat_contents)-1))
            randBallNumber = random.randint(0, len(_tempHat_contents)-1)
            #print(randBallNumber)
            #print(len(_tempHat_contents))
            ballDraw.append(_tempHat_contents[randBallNumber])
            #print(ballDraw)
            if len(_tempHat_contents) == 1:
                _tempHat_contents = copy.deepcopy(hat.contents)
                #print("WHaT?!")
            else:
                _tempHat_contents.remove(_tempHat_contents[randBallNumber])
                #print(len(_tempHat_contents))
            #print(ballDraw)
            #print(_tempHat_contents)
            q = q+1
            #countUp = countUp + 1
        #print("ballDraw = ", ballDraw)
        if ballDraw == None:
          print("WOW! You screwed up somewhere!")
          continue
        else:
            _tempMultiBall = copy.copy(multipleBalls)
            for x in ballDraw:
                if x in _tempMultiBall:
                    #print(x)
                    #print(_tempMultiBall)
                    _tempMultiBall.remove(x)
                    #print(_tempMultiBall)
                if _tempMultiBall == []:
                    #print("What?!")
                    counter = counter + 1
                    break


    # The experiment function should return a probability.
    return(counter/num_experiments)

Notice that each of the num_experiments experiment should start with the same hat. Otherwise experiments will not have the same initial values.

Well, to be completely honest, the bottom function has been reworked and noted and commented so many times it’s basically unreadable. I think I’m going to just start a new version of my code and delete the whole bottom function and start fresh. It sounds defeatist, but I’ll take what I’ve learned from writing it the first one thousand times and apply it =)

Thanks for your help, though and I may be back to ask again if I can’t work it out!

Yep, starting over did it. I super appreciate your help. It really did help. I went back and fixed my Draw function and got it to work (which I should have done in the first place), and rewrote my experiment function from scratch (it was a MESS!), with fresh eyes and finished it up. It went in half the time of me reworking it over and over again.

Thanks so much for trying. You did help guide me through on my second try =)

1 Like