
Generating all permutations, combinations, and power set of a string (2012) - rimher
http://exceptional-code.blogspot.com/2012/09/generating-all-permutations.html
======
RodgerTheGreat
There's a simple iterative alternative for generating power sets. For each
item of a set, you will either include it or exclude it in one of the results.
If you count from 0 to 2^n, the binary digits of your counter will enumerate
every combination of these possibilities. In Java 8:

    
    
        static <T> Set<Set<T>> power(List<T> a) {
          return IntStream.range(0, 1 << a.size())
          .mapToObj(x -> IntStream.range(0, a.size())
            .filter(y -> (1 << y & x) != 0)
            .mapToObj(y -> a.get(y))
            .collect(Collectors.toSet())
          ).collect(Collectors.toSet());
        }
    

In JS/ES6:

    
    
        function power(a) {
          var r = [];
          for(var x = (1 << a.length) - 1; x >= 0; x--) {
            r.push(a.filter((y, i) => 1 << i & x));
          }
          return r;
        }
    

In K6:

    
    
        {x@&:'+!(#x)#2}

~~~
bogomipz
>"For each item of a set, you will either include it or exclude it in one of
the results."

I found this interesting. This may be a silly question(my combinatorics
knowledge is limited) but what exactly is the relationship between power sets
and "N choose K"?

~~~
cpchen
The classic recurrence is if you're choosing K elements out of N, it either
has the first element (in which case you choose K-1 elements out of the
remaining N-1) or it doesn't (in which case you choose K elements out of the
remaining N-1), so:

N choose K = (N-1 choose K-1) + (N-1 choose K).

Also, if you sum (N choose K) for all values of K you get 2^N.

~~~
daenz
I came at this from the perspective of the Binomial theorem:

(x + y)^n = sum{k=0,n} (n choose k) x^(n-k) y^k

And since a powerset is:

sum{k=0,n} (n choose k)

The way we can turn the first equation into a powerset is by setting x=1 and
y=1, hence:

2^n = sum{k=0,n} (n choose k)

------
fjfaase
I prefer the use of iterators, instead of generating a whole collection. An
example of a permutation iterator in C++ is:

    
    
        class Permutations
        {
        public:
            Permutations(int val_n) : n(val_n), _more(true)
            {
                a = new int[n];
                for (int i = 0; i < n; i++)
                    a[i] = i;
            }
            ~Permutations()
            {
                delete []a;
            }
            bool more() { return _more; }
            void next()
            {
                _more = false;
                for (int i = n-2; i >= 0; i--)
                    if (a[i] < a[i+1])
                    {
                        _more = true;
                        for (int j = n-1; j > i; j--)
                            if (a[j] > a[i])
                            {
                                swap(a[j], a[i]);
                                break;
                            }
                        i++;
                        for (int j = n-1; j > i; j--, i++)
                            swap(a[j], a[i]);
                        break;
                    }
            }
            int operator[](int i) { return a[i]; }
                
            int n;
        private:
            void swap(int &x, int &y)
            {
                int h = x;
                x = y;
                y = h;
            }
            bool _more;
            int *a;
        };

------
dandermotj
If anyone wants to know how deep down the rabbit hole this stuff goes, they
should read this blog post [1] on writing a Levenshtein Automaton to speed up
fuzzy matching in Lucene by 100 times. It gets deep!

[1]: [http://blog.mikemccandless.com/2011/03/lucenes-fuzzyquery-
is...](http://blog.mikemccandless.com/2011/03/lucenes-fuzzyquery-is-100-times-
faster.html)

~~~
dbhattar
I am going to have to go through [1] referenced in the post.

[1]:
[http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.16.6...](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.16.652)

------
forinti
You can use binary to help generate your combinations of k elements (every
number of n bits with k 1s represents a combination of n-choose-k):
[http://alquerubim.blogspot.com.br/2012/05/combinacoes-de-
dig...](http://alquerubim.blogspot.com.br/2012/05/combinacoes-de-digitos-
ii.html)

And you can use factoradics to generate your permutations (because the
leftmost digit tells you which is the next element):
[http://alquerubim.blogspot.com.br/2012/06/combinacoes-de-
dig...](http://alquerubim.blogspot.com.br/2012/06/combinacoes-de-digitos-
iii.html)

So you transform your problem into counting. You just have to choose a
suitable base.

------
helicon
Posts like this are why I love HN. I recently wrote a program to find anagrams
of a given string (a Countdown solver if you live in the UK).

It includes a really naive method for generating all possible permutations of
the string, but reading this post I can immediately see a far better way to do
it.

That's my weekend taken care of! thanks to the poster and author.

~~~
forinti
There was a recent post about anagrams and the author just put all the letters
in alphabetical order and then compared the words, which was more efficient
than generating permutations.

~~~
NegativeLatency
Sounds interesting, do you have a link?

~~~
forinti
[http://blog.plover.com/lang/anagram-
scoring.html](http://blog.plover.com/lang/anagram-scoring.html)

------
rajathagasthya
Python recursive solution for generating permutations:

    
    
      s = 'abcd'
      prefix = ''
      permutation(prefix, s)
    
      def permutation(prefix, s):
          n = len(s)
          if n == 0:
              print(prefix)
          else:
              for i in range(n):
                  permutation(prefix + s[i], s[:i] + s[i+1:])

~~~
raymondh
An iterative Python recipe can be found in the docs:
[https://docs.python.org/3/library/itertools.html#itertools.p...](https://docs.python.org/3/library/itertools.html#itertools.permutations)

~~~
rajathagasthya
Straight from the horse's mouth! Thanks, Raymond :)

------
renesd
Python standard lib...

    
    
      import itertools
      list(itertools.permutations('abc'))

------
faragon
Nice post. I don't know why there is no a bigger push in
experiments/investigations with tree-like massive combinatorial expansion with
lazy-evaluation, so the solution space can be somewhat "reasonable" (e.g.
assuming you have infinite combinatorial expansion capability, adding
restrictions, so once you start the evaluation most of the combinations get
discarded, so you'll have to deal with a "sparse combinatorial expansion"
analog to a convex space for solutions in geometry).

------
vram22
Interesting thread.

Apropos of permutations, I had written these two posts a few months ago:

Permutation facts:

[https://jugad2.blogspot.in/2016/10/by-vasudev-ram-
nicomachus...](https://jugad2.blogspot.in/2016/10/by-vasudev-ram-nicomachus-
theorem-3d.html)

perm_facts version with list comps and functional programming:

[https://jugad2.blogspot.in/2016/10/permfacts-version-with-
li...](https://jugad2.blogspot.in/2016/10/permfacts-version-with-list-comps-
and.html)

The first post above also has some interesting facts about factorials, their
occurrences and applications, which was a revelation to me.

------
bograt
In Java there are libraries for this (as with most things):
[https://github.com/tomgibara/permute](https://github.com/tomgibara/permute)

------
tyingq
I don't know how efficient it is, but the bsd glob() function in their c
stdlib can generate unique permutations with brace syntax. If you wanted all
permutations of "abc", you would pass it "{a,b,c}{a,b,c}{a,b,c}"

It's also easy to get to bsd's glob() on non-bsd platforms with Perl:

    
    
      perl -MFile::Glob=bsd_glob -e 'print bsd_glob("{a,b,c}{a,b,c}{a,b,c}\n");'

------
sharmajai
Note the sub-optimality of _generatePermutations_.

For the second but last level (which will be entered _n_! times) it is doing
_n_ iterations which gives us a (not so tight) lower bound of _n_ * _n_!
instead of the optimal _n_!.

The issue is the use of an array for _visited_ instead of, say, a linked list
where each level gets a list of only unvisited nodes.

------
user2994cb
Generating necklaces and bracelets is fun too, see eg.
[http://www.sciencedirect.com/science/article/pii/S0304397512...](http://www.sciencedirect.com/science/article/pii/S0304397512010547)

------
bluetwo
I am curious where you would use something like this. I've worked with Minimum
Edit Distance, which is similar (what is the minimum number of steps to
convert one string into another).

Not sure where you would need to pull together all variations of the string
and apply it to a problem.

~~~
Scea91
It is true that due to complexity reasons,enumerating all combinations is
usually avoided. However, in my opinion it is useful to know how to do things
the basic way when learning more advanced algorithms such as RANSAC, APRIORI
and others...

------
zmonx
Very nice, thank you for sharing!

For comparison, here are Prolog solutions for these tasks.

The first building block is a _relation_ between a list, one of its elements,
and the list of _remaining_ elements:

    
    
        list_element_rest([E|Ls], E, Ls).
        list_element_rest([L|Ls0], E, [L|Ls]) :-
                list_element_rest(Ls0, E, Ls).
    

In the following, I assume you have set double_quotes to chars, so that you
can easily work on a string as a list of _characters_ :

    
    
        :- set_prolog_flag(double_quotes, chars).
    

Here is a sample interaction, using this relation:

    
    
        ?- list_element_rest("abc", E, Ls).
        E = a,
        Ls = [b, c] ;
        E = b,
        Ls = [a, c] ;
        E = c,
        Ls = [a, b] ;
        false.
    

Importantly, we can use it in _all_ directions, for example also to _insert_
an element _into_ a list:

    
    
        ?- list_element_rest(Ls, a, "bc").
        Ls = [a, b, c] ;
        Ls = [b, a, c] ;
        Ls = [b, c, a] ;
        false.
    

Using list_element_rest/3 as a building block, we can define the relation
between a list and one of its _permutations_ as follows:

    
    
        list_permutation([], []).
        list_permutation([L|Ls], Ps) :-
                list_permutation(Ls, Ps0),
                list_element_rest(Ps, L, Ps0).
    

This completes the first task. Example:

    
    
        ?- list_permutation("abc", Ps).
        Ps = [a, b, c] ;
        Ps = [b, a, c] ;
        Ps = [b, c, a] ;
        Ps = [a, c, b] ;
        Ps = [c, a, b] ;
        Ps = [c, b, a] ;
        false.
    

In many Prolog implementations, this predicate is already implemented as
permutation/2, but the point here is to show that you can also implement it
easily yourself, at least in the input->output direction, where the first
argument is fully instantiated.

To solve both the second _and_ third task, let us relate a list to one of its
_subsequences_ :

    
    
        subseq([]) --> [].
        subseq([L|Ls]) --> ([] | [L]), subseq(Ls).
    

With this definition, you can for example get all 2-element combinations of
"abcd" as follows:

    
    
        ?- length(Ls, 2), phrase(subseq("abcd"), Ls).
        Ls = [c, d] ;
        Ls = [b, d] ;
        Ls = [b, c] ;
        Ls = [a, d] ;
        Ls = [a, c] ;
        Ls = [a, b] ;
        false.
    

The _powerset_ is a natural _generalization_ of this query, where you simply
_omit_ the first goal:

    
    
        ?- phrase(subseq("abcd"), Ls).
        Ls = [] ;
        Ls = [d] ;
        Ls = [c] ;
        Ls = [c, d] ;
        Ls = [b] ;
        Ls = [b, d] ;
        Ls = [b, c] ;
        Ls = [b, c, d] ;
        Ls = [a] ;
        Ls = [a, d] ;
        Ls = [a, c] ;
        Ls = [a, c, d] ;
        Ls = [a, b] ;
        Ls = [a, b, d] ;
        Ls = [a, b, c] ;
        Ls = [a, b, c, d].

------
threepipeproblm
Thanks! I've been looking into this topic and the article is very helpful.

------
agumonkey
ha, fun.. I used to choke so much on powersets, after reading a lot I finally
got the recursive version; here in python (I know, but I couldn't find back my
lisp/ml version so..)

[https://gist.github.com/agumonkey/6ab51dfa759ef1993c55](https://gist.github.com/agumonkey/6ab51dfa759ef1993c55)

------
mroll
imo the coolest way to generate permutations
[https://en.m.wikipedia.org/wiki/Factorial_number_system](https://en.m.wikipedia.org/wiki/Factorial_number_system)

~~~
taeric
I'm partial to
[https://en.wikipedia.org/wiki/De_Bruijn_sequence](https://en.wikipedia.org/wiki/De_Bruijn_sequence).
:)

------
lgas
In Haskell:

    
    
        import Data.List ( subsequences )
        powerset = subsequences

~~~
RodgerTheGreat
It doesn't contribute much to the conversation to note that your favorite
language has a canned procedure for solving an algorithmic problem like this.
If you're genuinely interested in demonstrating Haskell's capabilities it
would be far more constructive to offer an _implementation_ of such a routine,
that it might be compared directly to the others in the article and this
thread.

~~~
SteveBash
There's a similar "canned procedure" a guy posted in python, why he wasn't
judged with the same severity, is there some kind of bias against Haskell
around here?

