Python Project Probability Calculator

Hey guys, there are similar questions but i couldn’t find a helping answer to my problem.

so the Output from running the test tells me

// running tests
The experiment method should return a different probability.
// tests completed

The example shown states the following

Here is how you would call the experiment function based on the example above with 2000 experiments:
hat = Hat(black=6, red=4, green=3)
probability = experiment(hat=hat,
expected_balls={“red”:2,“green”:1},
num_balls_drawn=5,
num_experiments=2000)
The output would be something like this:

0.356
Since this is based on random draws, the probability will be slightly different each time the code is run.

When i test my code i get numbers like these:
0.359
0.3535
0.364
0.3575
0.3625
0.373
0.3655
0.383
0.372
That seems “slightly different” to me…
how is “slightly different” defined? Unfortunately there are now other test examples.

Also interestingly the second test condition
“The draw method in hat class should reduce number of items in contents.”
does get a checkmark eventhough i think i#m not doing that. Here the method
def draw(s,anz):
returnliste=
if anz>len(s.contents):
return s.contents
conti=s.contents.copy() #<-- I copy the list and reduce the copy not the s.contents
for a in range(anz):
rand=random.randint(0,len(conti)-1)
returnliste.append(conti.pop(rand))
return returnliste

That just on the side it doesn’t bother me if it goes through.

By the way: I’m new here and i love it!

Generally the example says that because result depends on… well randomness. Tests are using the random module with specific seed, this allows to exactly reproduce the random values and receive exact expected results.

Could you share the complete code? Please put it between triple backticks to keep the formatting:

```
code here
```

import copy
import random

class Hat:
	def __init__(s,**kwargs):
		s.d = dict(**kwargs)
		#s.c=[ [a for a in s.d.keys()]]
		cont=[]
		for a in s.d.keys():
			for b in range(s.d[a]):
				cont.append(a)
		s.contents = cont
        
	def draw(s,anz):
		returnliste=[]
		if anz>len(s.contents):
			return s.contents
		conti=s.contents.copy()	
		for a in range(anz):
			rand=random.randint(0,len(conti)-1)
			returnliste.append(conti.pop(rand))
		return returnliste	


def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
	matching = []
	for a in expected_balls.keys():
		for b in range(expected_balls[a]):
			matching.append(a)
		
	mc = 0	
	for a in range(num_experiments):
		locount=0
		returnl = hat.draw(num_balls_drawn)
		for b in matching:
			if b in returnl:
				returnl.remove(b)
				locount+=1
		if 	locount==len(matching):
			mc+=1
	prob = mc/num_experiments	
	return prob	

i looked into the console after reading a similar post on the topic, but that doenst help me either
Ran 1 test in 0.010s pyodide.asm.js:9:119578
pyodide.asm.js:9:119578
FAILED (failures=1) pyodide.asm.js:9:119578
. pyodide.asm.js:9:119578
---------------------------------------------------------------------- pyodide.asm.js:9:119578
Ran 1 test in 0.000s pyodide.asm.js:9:119578
pyodide.asm.js:9:119578
OK pyodide.asm.js:9:119578
. pyodide.asm.js:9:119578
---------------------------------------------------------------------- pyodide.asm.js:9:119578
Ran 1 test in 0.001s pyodide.asm.js:9:119578
pyodide.asm.js:9:119578
OK pyodide.asm.js:9:119578
F pyodide.asm.js:9:119578
====================================================================== pyodide.asm.js:9:119578
FAIL: test_prob_experiment (test_module.UnitTests.test_prob_experiment) pyodide.asm.js:9:119578
---------------------------------------------------------------------- pyodide.asm.js:9:119578
Traceback (most recent call last): pyodide.asm.js:9:119578
File “/home/pyodide/test_module.py”, line 21, in test_prob_experiment pyodide.asm.js:9:119578
self.assertAlmostEqual(actual, expected, delta = 0.01, msg = ‘Expected experiment method to return a different probability.’) pyodide.asm.js:9:119578
AssertionError: 0.01 != 1.0 within 0.01 delta (0.99 difference) : Expected experiment method to return a different probability. pyodide.asm.js:9:119578
pyodide.asm.js:9:119578

Hmm, okay, I’ve investigated a bit (and confused myself a lot during that), second test is broken. It actually was already fixed in the codebase, but that fix didn’t yet reach production, once next deployment happens it should be fixed also on page.

Considering all this, the origin of the failing third test might be slightly surprising. I’ve added following code at the bottom, it’s kind of reproducing single experiment. Checking what is printed should give you some idea what is happening.

hat = Hat(red=4, green=2)
expected_balls={"red":2,"green":1}
matching = []
for a in expected_balls.keys():
	for b in range(expected_balls[a]):
		matching.append(a)
print('matching', matching)
locount=0
returnl = hat.draw(8)
print(hat.contents)
for b in matching:
	if b in returnl:
		returnl.remove(b)
		locount+=1
print(hat.contents)
1 Like

So what is happening in your single experiment is that for whatever reason returnl gets connected to hat.contents. Which i don’t understand why it is happening and one could investigate if that was the general problem. But if you insert the same print statements inside the experiment function at the exact same positions. Than weirdly hat.contents does not get linked to the returnl and hat.contents does not change itself at all… which adds confusion :confused:

Thank you a lot for your effort!

That’s caused by two things:

  • draw method returning contents list when number of balls to draw is higher than balls in hat.
  • experiment function doesn’t make sure to use fresh hat (fresh copy).

Because of that the returnl is actually the same list as hat.contents, not copy of it. So when balls are removed from returnl during the checking, they in fact will be removed from the hat.

1 Like

Oh wow… :dizzy_face: Thanks a lot man!!