# Probability calculator project, random module error

I’m getting an error when I run the test module. The traceback shows the error is coming from a method in the random module. I don’t understand what is going wrong. It looks like at some point `randrange` receives an empty range, but I have no idea how or why. Below I post the traceback and my experiment function.

``````======================================================================
ERROR: test_prob_experiment (test_module.UnitTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/denny/Sync/freeCodeCamp/scientific_computing_with_python/probability-calculator/test_module.py", line 29, in test_prob_experiment
probability = prob_calculator.experiment(hat=hat, expected_balls={"yellow":2,"blue":3,"test":1}, num_balls_drawn=20, num_experiments=100)
File "/home/denny/Sync/freeCodeCamp/scientific_computing_with_python/probability-calculator/prob_calculator.py", line 42, in experiment
balls = hat_copy.draw(num_balls_drawn)
File "/home/denny/Sync/freeCodeCamp/scientific_computing_with_python/probability-calculator/prob_calculator.py", line 23, in draw
idx = random.randint(0, (num_balls_in_hat - 1))
File "/usr/lib/python3.10/random.py", line 370, in randint
return self.randrange(a, b+1)
File "/usr/lib/python3.10/random.py", line 353, in randrange
raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width))
ValueError: empty range for randrange() (0, 0, 0)

----------------------------------------------------------------------
Ran 3 tests in 0.008s

FAILED (errors=1)
``````

My experiment function:

``````def experiment(hat: Hat, expected_balls={}, num_balls_drawn=0, num_experiments=0) -> float:
M = 0

# convert expected balls from a dict to a list
expected_balls_list = []
for ball, quantity in expected_balls.items():
expected_balls_list += [ball] * quantity

for i in range(num_experiments):
hat_copy = copy.deepcopy(hat)
balls = hat_copy.draw(num_balls_drawn)

ebl_in_bl = True
for b in expected_balls_list:
if b in balls:
balls.remove(b)
else:
ebl_in_bl = False
break

if ebl_in_bl:
M += 1

return (M / num_experiments)
``````

How your `draw` method looks like? Looking just at the error message, perhaps there’s situation when only one ball is left in the hat, what would result in passing two `0`s to the `randint`.

My `draw` method:

``````    def draw(self, num_balls: int) -> list[str]:
balls = []
num_balls_in_hat = len(self.contents)
for i in range(num_balls):
idx = random.randint(0, (num_balls_in_hat - 1))
try:
balls.append(self.contents.pop(idx))
num_balls_in_hat = len(self.contents)
except:
continue

return balls
``````

I was a bit wrong, error happens when there’s `0` balls in hat. this makes call `random.randint(0, -1)` which results with exception.

I believe it is expected, that once all balls are drawn from the hat, they are supposed to be returned to it.