]> gitweb.factorcode.org Git - factor.git/commitdiff
math.combinatorics: adding all-unique-permutations.
authorJohn Benediktsson <mrjbq7@gmail.com>
Tue, 23 Mar 2021 00:25:56 +0000 (17:25 -0700)
committerJohn Benediktsson <mrjbq7@gmail.com>
Tue, 23 Mar 2021 00:25:56 +0000 (17:25 -0700)
basis/math/combinatorics/combinatorics-docs.factor
basis/math/combinatorics/combinatorics-tests.factor
basis/math/combinatorics/combinatorics.factor

index 538654dc1fc757f114beaca00ba6a9438ea3729c..f34f537cf02f1ab67da8bc5476b5df88fb8d8bd2 100644 (file)
@@ -118,6 +118,19 @@ HELP: next-permutation
 { $notes "Performs an in-place modification of " { $snippet "seq" } "." }
 { $examples { $example "USING: math.combinatorics prettyprint ;" "\"ABC\" next-permutation ." "\"ACB\"" } } ;
 
+HELP: all-unique-permutations
+{ $values { "seq" sequence } { "seq'" sequence } }
+{ $description "Outputs a sequence containing all " { $strong "unique" } " permutations of " { $snippet "seq" } " in lexicographical order." }
+{ $examples
+    { $example "USING: math.combinatorics prettyprint ;"
+        "{ 1 1 2 } all-unique-permutations ."
+        "{ { 1 1 2 } { 1 2 1 } { 2 1 1 } }" }
+} ;
+
+HELP: each-unique-permutation
+{ $values { "seq" sequence } { "quot" { $quotation ( ... elt -- ... ) } } }
+{ $description "Applies the quotation to each " { $strong "unique" } " permutation of " { $snippet "seq" } " in order." } ;
+
 HELP: all-subsets
 { $values { "seq" sequence } { "subsets" sequence } }
 { $description
index 3accc2f6e63ef08fc404efe9509d20a881d02c14..e18771e3332b2c9c77179fd24c8532ac92860638 100644 (file)
@@ -1,5 +1,5 @@
 USING: arrays kernel math math.combinatorics
-math.combinatorics.private tools.test sequences ;
+math.combinatorics.private tools.test sequences sets ;
 
 { 1 } [ -1 factorial ] unit-test ! required by other math.combinatorics words
 { 1 } [ 0 factorial ] unit-test
@@ -100,6 +100,11 @@ math.combinatorics.private tools.test sequences ;
 { f } [ { 1 2 3 } [ last 4 = ] find-permutation ] unit-test
 { { 2 1 3 } } [ { 1 2 3 } [ first 2 = ] find-permutation ] unit-test
 
+{ t } [
+    { 1 1 1 1 1 1 1 1 2 }
+    [ all-permutations members ] [ all-unique-permutations ] bi =
+] unit-test
+
 { { { 0 1 2 } { 0 2 1 } { 1 0 2 } { 1 2 0 } { 2 0 1 } { 2 1 0 } } }
 [ 3 <iota> <permutations> >array ] unit-test
 
index f2aefb985d1b042219c9becbfe1198b300bdd22a..5d4a0d7b2695e95df7d613c7e7db7ca0bc839186 100644 (file)
@@ -2,8 +2,8 @@
 ! See http://factorcode.org/license.txt for BSD license.
 
 USING: accessors arrays assocs classes.tuple combinators hints
-kernel kernel.private math math.functions math.order math.ranges
-sequences sequences.private sorting strings vectors ;
+kernel kernel.private make math math.functions math.order
+math.ranges sequences sequences.private sorting strings vectors ;
 IN: math.combinatorics
 
 <PRIVATE
@@ -154,6 +154,31 @@ PRIVATE>
 : next-permutation ( seq -- seq )
     dup empty? [ (next-permutation) ] unless ;
 
+<PRIVATE
+
+: should-swap? ( start curr seq -- ? )
+    [ nipd nth ] [ <slice> member? not ] 3bi ; inline
+
+:: unique-permutations ( ... seq i n quot: ( ... elt -- ... ) -- ... )
+    i n >= [
+        seq clone quot call
+    ] [
+        i n [a..b) [| j |
+            i j seq should-swap? [
+                i j seq exchange-unsafe
+                seq i 1 + n quot unique-permutations
+                i j seq exchange-unsafe
+            ] when
+        ] each
+    ] if ; inline recursive
+
+PRIVATE>
+
+: each-unique-permutation ( ... seq quot: ( ... elt -- ... ) -- ... )
+    [ 0 over length ] dip unique-permutations ; inline
+
+: all-unique-permutations ( seq -- seq' )
+    [ [ , ] each-unique-permutation ] { } make ;
 
 ! Combinadic-based combination methodology