Generando permutaciones con repeticiones


84

Sé sobre itertools, pero parece que solo puede generar permutaciones sin repeticiones.

Por ejemplo, me gustaría generar todas las tiradas de dados posibles para 2 dados. Entonces necesito todas las permutaciones de tamaño 2 de [1, 2, 3, 4, 5, 6], incluidas las repeticiones: (1, 1), (1, 2), (2, 1) ... etc.

Si es posible, no quiero implementar esto desde cero.

Respuestas:


144

Busca el producto cartesiano .

En matemáticas, un producto cartesiano (o conjunto de productos) es el producto directo de dos conjuntos.

En su caso, esto sería {1, 2, 3, 4, 5, 6}x {1, 2, 3, 4, 5, 6}. itertoolspuede ayudarte allí:

import itertools
x = [1, 2, 3, 4, 5, 6]
[p for p in itertools.product(x, repeat=2)]
[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 1), (2, 2), (2, 3), 
 (2, 4), (2, 5), (2, 6), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6), 
 (4, 1), (4, 2), (4, 3), (4, 4), (4, 5), (4, 6), (5, 1), (5, 2), (5, 3), 
 (5, 4), (5, 5), (5, 6), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (6, 6)]

Para obtener una tirada de dados aleatoria (de una manera totalmente ineficiente ):

import random
random.choice([p for p in itertools.product(x, repeat=2)])
(6, 3)

8
Esta es una forma extremadamente ineficiente de obtener 2 tiradas de dados… Dos llamadas a random.randintsería más simple y más eficiente.
Eric O Lebigot

Las tiradas de dados aleatorios serán mucho más rápidas cuando no genere todos los pares posibles: [random.randint (1,6) for i in xrange (2)]
liori

13
En realidad, no estaba tratando de generar tiradas aleatorias, solo para enumerar todas las tiradas posibles.
Bwmat


7

En python 2.7 y 3.1 hay una itertools.combinations_with_replacementfunción:

>>> list(itertools.combinations_with_replacement([1, 2, 3, 4, 5, 6], 2))
[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 2), (2, 3), (2, 4), 
 (2, 5), (2, 6), (3, 3), (3, 4), (3, 5), (3, 6), (4, 4), (4, 5), (4, 6),
 (5, 5), (5, 6), (6, 6)]

12
Esta solución pierde hacia fuera en las combinaciones (2, 1), (3, 2), (3, 1)y similares ... En general, se deja de lado todas las combinaciones en las que el segundo rollo es inferior a la primera.
holroy

1

En este caso, la comprensión de una lista no es particularmente necesaria.

Dado

import itertools as it


seq = range(1, 7)
r = 2

Código

list(it.product(seq, repeat=r))

Detalles

Evidentemente, el producto cartesiano puede generar subconjuntos de permutaciones. Sin embargo, se deduce que:

  • con reemplazo: producir todas las permutaciones n r víaproduct
  • sin recambio: filtro de este último

Permutaciones con reemplazo, n r

[x for x in it.product(seq, repeat=r)]

Permutaciones sin reemplazo, n!

[x for x in it.product(seq, repeat=r) if len(set(x)) == r]
# Equivalent
list(it.permutations(seq, r))  

En consecuencia, todas las funciones combinatorias podrían implementarse desde product:


-1

Creo que encontré una solución usando solo lambdas, mapy reduce.

product_function = lambda n: reduce(lambda x, y: x+y, map(lambda i: list(map(lambda j: (i, j), np.arange(n))), np.arange(n)), [])

Básicamente, estoy mapeando una primera función lambda que, dada una fila, itera las columnas

list(map(lambda j: (i, j), np.arange(n)))

entonces esto se usa como la salida de una nueva función lambda

lambda i:list(map(lambda j: (i, j), np.arange(n)))

que se asigna a todas las filas posibles

map(lambda i: list(map(lambda j: (i, j), np.arange(n))), np.arange(m))

y luego reducimos todas las listas resultantes a una.

aun mejor

También puede utilizar dos números diferentes.

prod= lambda n, m: reduce(lambda x, y: x+y, map(lambda i: list(map(lambda j: (i, j), np.arange(m))), np.arange(n)), [])

-2

Primero, primero querrá convertir el generador devuelto por itertools.permutations (list) en una lista. Luego, en segundo lugar, puede usar set () para eliminar duplicados, algo como a continuación:

def permutate(a_list):
    import itertools
    return set(list(itertools.permutations(a_list)))

1
Eso no incluye duplicados.
Björn Lindqvist

1
OP explícitamente quiere duplicados
Levi Lesches
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.