2010-06-23 18 views
41

So di itertools, ma sembra che possa generare permutazioni senza ripetizioni.generando permutazioni con ripetizioni in python

per esempio, mi piacerebbe generare tutti i possibili lanci di dadi per 2 dadi. Così ho bisogno di tutte le permutazioni di dimensione 2 di [1, 2, 3, 4, 5, 6] tra ripetizioni: (1, 1), (1, 2), (2, 1) ... ecc

Se possibile, non voglio implementare questo da zero

risposta

68

stai cercando il Cartesian Product.

In matematica, un prodotto cartesiano (o set di prodotti) è il prodotto diretto di due serie.

Nel tuo caso, questo sarebbe {1, 2, 3, 4, 5, 6} x {1, 2, 3, 4, 5, 6}. itertools può aiutare lì:

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

Per ottenere un lancio di dadi casuale (in maniera del tutto inefficiente):

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

Riscritta mio post. – miku

+5

Questo è un modo estremamente inefficiente di ottenere 2 lanci di dadi ... Due chiamate a 'random.randint' sarebbero più semplici e più efficienti. – EOL

+0

I lanci casuali dei dadi saranno molto più veloci quando non genererai tutte le coppie possibili: [random.randint (1,6) per i in xrange (2)] – liori

20

non siete in cerca di permutazioni - si desidera che il Cartesian Product. Per questo uso product da itertools:

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

Puoi semplicemente fare 'product (die, repeat = 2)': non c'è bisogno dell'elenco 'dice'. – EOL

+0

Buon punto, grazie. –

+0

Lo trovo il più leggibile. –

2

in Python 2.7 e 3.1 esiste una funzione 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

Questa soluzione si perde sulle combinazioni '(2, 1)', '(3, 2)', '(3, 1)' e simili ... In generale, lascia fuori tutte le combinazioni in cui il secondo tiro è inferiore a il primo. La domanda – holroy

-3

Ecco C# versione (anche se la sua richiesta per Python, l'algoritmo dovrebbe essere lo stesso) solo per riferimento:

Di seguito il metodo prende sostanzialmente no. di volte i dadi possono essere lanciati per ottenere varie permutazioni. Per la domanda di cui sopra, la dimensione dovrebbe essere '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); 
      } 
     } 

per tirare i dadi due volte, il metodo di cui sopra può essere definito come:

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

seguito sono corrispondenti unit test:

[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

riguardava Python non C – m1k3y3

-1

prima cosa, vuoi prima trasformare il generatore restituito da itertools.permutations (list) in una lista. Poi in secondo luogo, è possibile utilizzare set() per rimuovere i duplicati Qualcosa come di seguito:

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

Ciò non include i duplicati. –

+0

OP richiede esplicitamente duplicati –

Problemi correlati