Pergunta

Para uma lista de 10 ints, existem 10! possíveis ordens ou permutações. Por que aleatoriamente.Flue dá duplicatas após apenas 5000 tentativas?

>>> L = range(10)
>>> rL = list()
>>> for i in range(5000):
...     random.shuffle(L)
...     rL.append(L[:])
... 
>>> rL = [tuple(e) for e in rL]
>>> len(set(rL))
4997
>>> for i,t in enumerate(rL):
...     if rL.count(t) > 1:
...         print i,t
... 
102 (7, 5, 2, 4, 0, 6, 9, 3, 1, 8)
258 (1, 4, 0, 2, 7, 3, 5, 9, 6, 8)
892 (1, 4, 0, 2, 7, 3, 5, 9, 6, 8)
2878 (7, 5, 2, 4, 0, 6, 9, 3, 1, 8)
4123 (5, 8, 0, 1, 7, 3, 2, 4, 6, 9)
4633 (5, 8, 0, 1, 7, 3, 2, 4, 6, 9)
>>> 10*9*8*7*6*5*4*3*2
3628800
>>> 2**19937 - 1
431542479738816264805523551633791983905393 [snip]

>>> L = list()
>>> for i in range(5000):
...     L.append(random.choice(xrange(3628800)))
... 
>>> len(set(L))
4997

Editar: FWIW, se a probabilidade de não ter dois iguais para um único par é: p = (10! - 1) / 10! E o número de combinações é: c = 5000! / 4998! * 2! = 5000 * 4999 /2 Então a probabilidade de ter uma duplicata é:

>>> import math
>>> f = math.factorial(10)
>>> p = 1.0*(f-1)/f
>>> C = 5000.0*4999/2
>>> 1 - p**C
0.96806256495611798
Foi útil?

Solução

É chamado de Paradoxo de aniversário.

De acordo com esta fórmula da Wikipedia:

mas substituindo 365 com 10! Você precisaria apenas de 2200 exemplos para ter 50% de chance de uma colisão, e está muito acima disso.

Outras dicas

Porque é ... aleatório! Se você deseja todas as permutações, basta usar o itertools.permutações.

Talvez porque seja aleatório? Random não significa que não se repete, significa que é aleatório, o que significa que, teoricamente, pode retornar exatamente a mesma resposta sempre, não provável, mas possível.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top