bwmat
Supongamos que tengo una lista die_faces = [1, 2, 3, 4, 5, 6]
. Quiero generar los 36 resultados posibles para lanzar dos dados: (1, 1)
, (1, 2)
, (2, 1)
etc. Si trato de usar permutations
desde el itertools
biblioteca estándar:
>>> import itertools
>>> die_faces = [1, 2, 3, 4, 5, 6]
>>> list(itertools.permutations(die_faces, 2))
[(1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 1), (2, 3), (2, 4), (2, 5), (2, 6), (3, 1), (3, 2), (3, 4), (3, 5), (3, 6), (4, 1), (4, 2), (4, 3), (4, 5), (4, 6), (5, 1), (5, 2), (5, 3), (5, 4), (5, 6), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5)]
solo hay 30 resultados, faltando aquellos en los que sale el mismo número en ambos dados. Parece que solo genera permutaciones sin repeticiones. ¿Cómo puedo arreglar esto?
miku
estas buscando el Producto cartesiano.
En matemáticas, un producto cartesiano (o conjunto de productos) es el producto directo de dos conjuntos.
En tu caso, esto sería {1, 2, 3, 4, 5, 6}
X {1, 2, 3, 4, 5, 6}
.
itertools
te puede ayudar ahi:
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 al azar (en un manera totalmente ineficiente):
import random
random.choice([p for p in itertools.product(x, repeat=2)])
(6, 3)
-
Esta es una forma extremadamente ineficiente de obtener 2 tiradas de dados… Dos llamadas a
random.randint
sería más simple y eficiente.– Eric O Lebigot
23 de junio de 2010 a las 9:39
-
Las tiradas aleatorias de dados serán mucho más rápidas cuando no generes todos los pares posibles: [random.randint(1,6) for i in xrange(2)]
– liori
23 de junio de 2010 a las 9:42
-
En realidad, no estaba tratando de generar tiradas aleatorias, solo para enumerar todas las tiradas posibles.
– Bwmat
23 de junio de 2010 a las 10:18
marca byers
No está buscando permutaciones, quiere la 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)
En python 2.7 y 3.1 hay un itertools.combinations_with_replacement
funció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)]
-
Esta solución pierde en las combinaciones
(2, 1)
,(3, 2)
,(3, 1)
y similares… En general omite todas las combinaciones donde el segundo rollo es más bajo que el primero.– Holroy
16 de noviembre de 2015 a las 18:48
-
¡Tal vez no sea la solución “correcta”, sino la correcta para mí! ¡Gracias!
– jbm
21 oct 2021 a las 0:16
-
tengo que votar negativamente ya que @holroy tiene razón y esto puede ser confuso
– shabunc
21 de abril de 2022 a las 10:35
pilang
En este caso, una lista de comprensión no es particularmente necesaria.
Dado
import itertools as it
seq = range(1, 7)
r = 2
Código
list(it.product(seq, repeat=r))
Detalles
Obviamente, el producto cartesiano puede generar subconjuntos de permutaciones. Sin embargo, se sigue que:
- con reemplazo: producir todas las permutaciones nr a través de
product
- sin reemplazo: filtro de este último
Permutaciones con reemplazo, nr
[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 a partir de product
:
combinations_with_replacement
implementado desdeproduct
combinations
implementado desdepermutations
que se puede implementar conproduct
(véase más arriba)
Euler_Salter
Creo que encontré una solución usando solo lambdas
, map
y 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)), [])
Esencialmente, 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 salida de una nueva función lambda
lambda i:list(map(lambda j: (i, j), np.arange(n)))
que se asigna a través de 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 en una sola.
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)), [])
Eric_HL_DoCode
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)))
Consulte también stackoverflow.com/questions/942543 para el caso de llamar directamente a una función con los nuevos valores.
– Karl Knechtel
3 de julio de 2022 a las 16:30