2011-01-04 36 views
7

Belirli bir listenin tüm permütasyonlarını üreten Scala listeleri için bir permütasyon jeneratörü yazdım. Şimdiye kadar, ben this Haskell implementation dayanarak aşağıdaki var (ve ben denedim diğer seçenekler daha verimli olduğunu düşünüyorum). Bunu daha da verimli hale getirmek için herhangi bir yol var mı yoksa tüm üslerimi mi kapsıyorum? 2.9 extempore skala koleksiyon sınıfı bazı faydalı yöntemler ekledik ScalaDaha hızlı geçirgenlik oluşturucu

/** 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

Bu, dizi tabanlı takas yönteminden daha mı hızlıdır? Yoksa "en hızlı fonksiyonel permütasyon jeneratörü" mi demek istiyorsun? (Açıkça asla söylemediniz, ama etiketi eklediniz ....) –

+0

En hızlı işlevsel permütasyon jeneratörü demek istiyorum. Bu nedenle, bunu dizi tabanlı takas yöntemiyle karşılaştırmayı denemediniz. –

+0

Daha iyi algoritmalar var. Scala'da bir süre önce Stack Overflow'da bir tane gördüm, ki bu da tüm permütasyonların bir listesi yerine bir sonraki permütasyona (bir dizi indeksler varsayılarak) geri döndü. Bir sonraki dizin permütasyonunun noktasını bulmak için 'bölüm 'kullandı ve genellikle kuyruksuz tekrarlı çağrılardan kaçınıldı. Ayrıca, şüphesiz Haskell'in göstermiş olduğunuz kodun uygulanması çok hızlı bir şekilde çalışacaktır çünkü herhangi bir ön-hesaplama yapmaz. :-) –

cevap

3

bu seq tüm permütasyonlarını üreten bir Seq.permutations bulunmaktadır. Bakınız link text. Ve daha iyi bir performansa sahip olacağını düşündüğüm, özyinelemeyen bir uygulama var. Bkz. A non-recursive implementation of SeqLike.permutations

+0

Eh, şimdi Scala 2.9 svn sürümünde benimki gibi benimki gibi görünüyor, sadece 10 öğe listesine izin vermeye çalışan bellek yetersiz çalışır ve benimkinden çok daha kötü bir performans var. Sürümünüz, kısa (5 öğe) listeler için benimkilerden daha yavaş, ancak daha uzun (10 öğe) listeler için daha hızlıdır. Ayrıca, bir defada daha az bellek kullanırsınız, çünkü bir yineleyici döndürürsünüz. –

+0

Kullanım durumum için, kopyaları denemek ve ortadan kaldırmak için işleri yavaşlatır, çünkü muhtemelen çoğaltılamaz ve '==' nesnelerimde uzun zaman alır (burada tartıştığım ölçütler bir Listeyle [Int ]). –

+0

Evet, Extempore veya uygulamam yinelenen örneklerle Seq olarak kullanılabilir. Liste (1,1,1,2,2,2) – Eastsun