2011-01-04 35 views
7

Tôi đã viết một bộ tạo hoán vị cho danh sách Scala tạo tất cả các hoán vị của một danh sách nhất định. Cho đến nay, tôi đã có những điều sau dựa trên this Haskell implementation (và tôi nghĩ rằng nó hiệu quả hơn so với một số tùy chọn khác mà tôi đã thử). Có cách nào để làm cho điều này thậm chí hiệu quả hơn, hoặc tôi đã bao trả tất cả các căn cứ của tôi?Máy phát hoán vị nhanh hơn

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

Điều này có nhanh hơn phương pháp hoán đổi dựa trên mảng không? Hoặc bạn có nghĩa là "máy phát điện hoán vị chức năng nhanh nhất"? (Bạn không bao giờ nói rõ như vậy, nhưng bạn đã thêm thẻ ....) –

+0

Tôi có nghĩa là trình tạo hoán vị chức năng nhanh nhất. Vì lý do đó, chưa thử so sánh điều này với phương thức hoán đổi dựa trên mảng. –

+0

Có các thuật toán tốt hơn. Tôi thấy một ở đây trên Stack Overflow cách đây không lâu, trong Scala, mà trả về hoán vị tiếp theo (giả sử một tập hợp các chỉ số), thay vì một danh sách tất cả các hoán vị. Nó sử dụng 'phân vùng' để tìm điểm của hoán vị chỉ mục tiếp theo, và thường tránh các cuộc gọi đệ quy không đuôi. Ngoài ra, tất nhiên, việc triển khai mã của Haskell mà bạn đã hiển thị sẽ chạy rất nhanh, bởi vì nó sẽ không tính toán bất cứ thứ gì lên phía trước. :-) –

Trả lời

3

Mở rộng Scala 2.9 đã thêm một số phương pháp hữu ích vào lớp thu thập dữ liệu, bao gồm một Seq.permutations tạo ra tất cả hoán vị của seq này. Xem link text. Và tôi có một triển khai không đệ quy mà tôi nghĩ rằng sẽ có hiệu suất tốt hơn. Xem A non-recursive implementation of SeqLike.permutations

+0

Vâng, phiên bản trong Scala 2.9 svn ngay bây giờ có vẻ tương tự như tôi trong sự implemetation của nó, chỉ có nó chạy ra khỏi bộ nhớ cố gắng để permute một danh sách 10 mục, và nó có hiệu suất tồi tệ hơn nhiều so với tôi. Phiên bản của bạn chậm hơn so với danh sách ngắn (5 mục) của tôi, nhưng nhanh hơn cho danh sách dài hơn (10 mục). Ngoài ra, bạn sử dụng ít bộ nhớ hơn một lần, vì bạn trả về một trình lặp. –

+0

Đối với trường hợp sử dụng của tôi, nó sẽ làm chậm mọi thứ để thử và loại bỏ các bản sao, vì có lẽ không có bản sao, và '==' trên các đối tượng của tôi mất một thời gian dài (mặc dù các điểm chuẩn mà tôi thảo luận ở đây đã được thực hiện với Danh sách [Int ]). –

+0

Có, Extempore hoặc triển khai của tôi có sẵn cho Seq với các bản sao, ví dụ: Danh sách (1,1,1,2,2,2) – Eastsun