From the description of the problem, I believe you’re doing some unnecessary things, it’s simpler than it seems.
What is the birthday paradox/problem?
Video explanatory PT
To simulate this we can do so:
- Receive as input the number of people (
num_p
) and number of tests/repetitions (num_loops
) to make;
- In each test we generate a list with
num_p
(number of people) random integers, each may have a value between 1 and 365 to simulate each person’s birthday. Ex: in a test with 6 people we can get [4, 144, 233, 98, 144, 43]
;
- Check if in the generated list there is any value that occurs more than once in the same list, in this case I use
any()
and count()
. Ex: [4, 144, 233, 98, 144, 43]
(birthdays of 6 people), in this case 144 is repeated, ie two people have the same birthday;
- If the point above (3) is checked is because we have at least 1 value that repeats, then we increment our variable
favoraveis
, and at the end of the tests calculate the percentage of favoraveis
in num_loops
(number of tests).
Code:
import random
num_p = int(input("Digite o número de pessoas: "))
num_loops = int(input("Digite o número de repetições: ")) # num de testes
favoraveis = 0
for _ in range(num_loops):
ani_dates = [random.randint(1, 366) for _ in range(num_p)] # sortear nova lista de datas (dias) de aniversario
if(any(ani_dates.count(i) > 1 for i in ani_dates)): # verificar se existe a mesma data (valor) mais do que uma vez na lista
favoraveis += 1
probs_perc = (favoraveis/num_loops)*100
print('Em {} pessoas e {} testes deram-se {} vezes em que pelo menos duas pessoas fazem anos no mesmo dia, percentagem: {}%'.format(num_p, num_loops, favoraveis, probs_perc))
# Em 23 pessoas e 1000 testes deram-se 504 vezes em que pelo menos duas pessoas fazem anos no mesmo dia, percentagem: 50.4%
# Em 57 pessoas e 1000 testes deram-se 993 vezes em que pelo menos duas pessoas fazem anos no mesmo dia, percentagem: 99.3%
DEMONSTRATION
Editing
After reviewing this response and performing some tests I noticed that we achieved a better performance if we make use of set()
and its characteristic of not storing duplicate values, so we can simply check whether the set
is different (smaller) than the number of people (num_p
), if it’s because there were duplicate values, and we had at least two people having their birthday on the same day (favoraveis += 1
):
import random
num_p = int(input("Digite o número de pessoas: "))
num_loops = int(input("Digite o número de repetições: ")) # num de testes
favoraveis = 0
for _ in range(num_loops):
ani_dates = {random.randint(1, 366) for _ in range(num_p)} # sortear novo set de datas (dias) de aniversario
if(len(ani_dates) != num_p): # se o comprimento do set for diferente do num de pessoas
favoraveis += 1
probs_perc = (favoraveis/num_loops)*100
print('Em {} pessoas e {} testes deram-se {} vezes em que pelo menos duas pessoas fazem anos no mesmo dia, percentagem: {}%'.format(num_p, num_loops, favoraveis, probs_perc))
# Em 23 pessoas e 1000 testes deram-se 506 vezes em que pelo menos duas pessoas fazem anos no mesmo dia, percentagem: 50.6%
DEMONSTRATION
The exponential probability increase equation may be seen here, and I while testing this same equation in python also made the graph.
It has nothing to do with the question but here I leave the code to make this graph:
import matplotlib.pyplot as plt
def birthday_probs(x):
p = (1.0/365)**x
for i in range((366-x),366):
p *= i
return 1-p
plt.plot([birthday_probs(i)*100 for i in range(366)])
plt.xlabel("Num de pessoas")
plt.ylabel("Probabilidades de partilha de dia de aniversário")
plt.ylim(ymin=0)
plt.xlim(xmin=0, xmax=80)
plt.show()
Write a battery of unit tests that reflect the expected behavior, then it is easy to identify which cases are not correct.
– thiagoalessio