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.

Bwmat
fuente

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)
miku
fuente
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
29

No busca permutaciones, desea el producto cartesiano . Para este uso producto de itertools:

from itertools import product
for roll in product([1, 2, 3, 4, 5, 6], repeat = 2):
    print(roll)
Mark Byers
fuente
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)]
SilentGhost
fuente
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:

pylang
fuente
-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)), [])
Euler_Salter
fuente
-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)))
Eric_HL_DoCode
fuente
1
Eso no incluye duplicados.
Björn Lindqvist
1
OP explícitamente quiere duplicados
Levi Lesches