2010-06-23 25 views
41

Conozco itertools, pero parece que solo puede generar permutaciones sin repeticiones.generando permutaciones con repeticiones en python

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

Si es posible, no quiero implementar esto desde cero

Respuesta

68

Está buscando el Cartesian Product.

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}. itertools puede ayudar a no:

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 (de una manera totalmente ineficaz):

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

Reescribió mi puesto. – miku

+5

Esta es una forma extremadamente ineficiente de obtener 2 tiradas de dados ... Dos llamadas a 'random.randint' serían más simples y más eficientes. – EOL

+0

Los rollos de dados aleatorios serán mucho más rápidos cuando no se generen todos los pares posibles: [random.randint (1,6) para i en xrange (2)] – liori

20

usted no está buscando permutaciones - desea que el Cartesian Product. Para este uso product de itertools:

from itertools import product 
for roll in product([1, 2, 3, 4, 5, 6], repeat = 2): 
    print(roll) 
+1

Puede simplemente hacer 'producto (morir, repetir = 2)': no hay necesidad de la lista 'dados '. – EOL

+0

Buen punto, gracias. –

+0

Encuentro esto el más legible. –

2

en Python 2.7 y 3.1 hay una función itertools.combinations_with_replacement:

>>> 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)] 
+4

Esta solución se pierde en las combinaciones '(2, 1)', '(3, 2)', '(3, 1)' y similares ... En general, omite todas las combinaciones donde la segunda tirada es menor que el primero. – holroy

-3

Aquí es C# versión (a pesar de que su pedido pitón, el algoritmo debe ser igual) sólo como referencia:

Por debajo del método, básicamente, no es necesario. de veces los dados pueden lanzarse para obtener varias permutaciones. Para la pregunta anterior, el tamaño debe ser '2'.

private void GetAllPermutationsOfDice_Recursive(int size, string currentValue, 
      List<string> values) 
     { 
      if(currentValue.Length == size) 
      { 
       values.Add(currentValue); 
       return; 
      } 
      for(int i = 1; i<=6;i++) 
      { 
       this.GetAllPermutationsOfDice_Recursive(size, currentValue + i, values); 
      } 
     } 

para tirar los dados dos veces, el método anterior puede ser llamado como:

public string[] GetAllPermutationsOfDiceOfSize_2() 
     { 
      List<string> values = new List<string>(); 
      this.GetAllPermutationsOfDice_Recursive(2, "", values); 
      return values.ToArray(); 
     } 

A continuación se presentan las pruebas de unidad correspondiente:

[TestMethod] 
     public void Dice_PermutationsTests() 
     { 
      var v = this.GetAllPermutationsOfDiceOfSize_2(); 
      Assert.AreEqual(36, v.Length); 
      int l = 6; 
      List<string> values = new List<string>(); 
      for(int i = 1; i<=4; i++) 
      { 
       values.Clear(); 
       this.GetAllPermutationsOfDice_Recursive(i, "", values); 
       Assert.AreEqual(l, values.Count); 
       l *= 6; 
      } 
     } 
+0

pregunta acerca de python no C – m1k3y3

-1

primer lugar, usted quiere activar primero el generador devuelto por itertools.permutations (list) en una lista. A continuación, en segundo lugar, puede utilizar set() para eliminar duplicados Algo parecido a continuación:

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

Eso no incluye duplicados. –

+0

OP explícitamente quiere duplicados –

Cuestiones relacionadas