2011-01-04 10 views
7

Ho scritto un generatore di permutazioni per liste Scala che genera tutte le permutazioni di una data lista. Finora, ho il seguente basato su this Haskell implementation (e penso che sia più efficiente di molte altre opzioni che ho provato). Ci sono dei modi per renderlo ancora più efficiente, o ho coperto tutte le mie basi?Generatore di permutazione più veloce

/** For each element x in List xss, returns (x, xss - x) */ 
    def selections[A](xss:List[A]):List[(A,List[A])] = xss match { 
     case Nil => Nil 
     case x :: xs => 
     (x, xs) :: (for((y, ys) <- selections (xs)) 
      yield (y, x :: ys)) 
    } 

    /** Returns a list containing all permutations of the input list */ 
    def permute[A](xs:List[A]):List[List[A]] = xs match { 
     case Nil => List(Nil) 

     //special case lists of length 1 and 2 for better performance 
     case t :: Nil => List(xs) 
     case t :: u :: Nil => List(xs,List(u,t)) 

     case _ => 
     for ((y,ys) <- selections(xs); ps <- permute(ys)) 
      yield y :: ps 
    } 
+1

È più veloce del metodo di scambio basato su array? O intendi "generatore di permutazione funzionale più veloce"? (Non lo hai mai detto esplicitamente, ma hai aggiunto il tag ....) –

+0

Intendo il generatore di permutazione funzionale più veloce. Per questo motivo, non ho provato a confrontarlo con il metodo di swap basato su array. –

+0

Ci sono algoritmi migliori. Ne ho visto uno qui su Stack Overflow non molto tempo fa, in Scala, che ha restituito la permutazione successiva (assumendo un insieme di indici), invece di una lista di tutte le permutazioni. Ha usato 'partition' per trovare il punto della successiva permutazione dell'indice e, in generale, ha evitato le chiamate ricorsive non-tail. Inoltre, ovviamente, l'implementazione di Haskell del codice che hai mostrato sarebbe stata molto veloce, perché non avrebbe calcolato nulla in anticipo. :-) –

risposta

3

In Scala 2.9 estemporanea hanno aggiunto alcuni metodi utili alla classe di raccolta scala, includono un Seq.permutations che genera tutte le permutazioni di questo ss. Vedi link text. E ho un'implementazione non ricorsiva che penso avrebbe una performance migliore. Vedere A non-recursive implementation of SeqLike.permutations

+0

Bene, la versione in svn di Scala 2.9 in questo momento sembra essere simile alla mia nella sua implementazione, solo che esaurisce la memoria cercando di permutare una lista di 10 elementi, e ha prestazioni molto peggiori della mia. La tua versione è più lenta della mia per elenchi brevi (5 articoli), ma più veloce per elenchi più lunghi (10 articoli). Inoltre, si utilizza meno memoria in una volta, perché si restituisce un iteratore. –

+0

Per il mio caso d'uso, rallenterebbe le cose per cercare di eliminare i duplicati, perché presumibilmente non ci sono duplicati, e '==' sui miei oggetti richiede molto tempo (anche se i benchmark che discuto qui sono stati eseguiti con un List [Int ]). –

+0

Sì, Extempore o la mia implementazione sono disponibili per Seq con duplicati, ad es. List (1,1,1,2,2,2) – Eastsun