gprime
gprime

Reputation: 2353

Permuting All Possible (0, 1) value arrays

I am having writing an algorithm to generate all possible permutations of an array of this kind:

n = length
k = number of 1's in array

So this means if we have k 1's we will have n-k 0's in the array.

For example: n = 5; k = 3;

So obviously there are 5 choose 3 possible permutations for this array because
n!/(k!(n-k)!
5!/(3!2!) = (5*4)/2 = 10
possible values for the array

Here are all the values:
11100
11010
11001
10110
10101
10011
01110
01101
01011
00111

I am guessing i should use a recursive algorithms but i am just not seeing it. I am writing this algorithm in C++.

Any help would be appreciated!

Upvotes: 0

Views: 2665

Answers (7)

Steve Jessop
Steve Jessop

Reputation: 279335

If you want to do this recursively, observe that the set of permutations you want is equal to all the ones that start with "1", together with all the ones that start with "0". So in calculating (n,k), you will recurse on (n-1,k-1) and (n-1,k), with special cases where k = 0 and k = n.

This recursion is the reason that the binomial coefficients appear as the values in Pascal's triangle.

Upvotes: 2

Adesit
Adesit

Reputation: 159

Its about 0-1 permutations, so probably its much more eficient to iteratively increment an integer and in case it has desired bits count, print out its binary representation.

Here a sketch:

void printAllBinaryPermutations(int k, int n)  
{  
  int max = pow(2, n) - 1;  
  for(int i=0; i<=max;i++)  
  {  
    if(hasBitCountOf(i, k)) // i has k 1's?  
    {  
      printAsBinary(i, n);  
    }  
  }  
}  


bool hasBitCountOf(int v, int expectedBitCount)  
{  
    int count = 0;  
    while(v>0 && count<= expectedBitCount)  
    {  
        int half = v >> 1;  
        if(half<<1 != v)  
        {  
            // v is odd  
            count++;  
        }  
        v = half;  
    }  

    return count==expectedBitCount;  
}  


void printAsBinary(int number, int strLen)  
{  
  for(int i=strLen-1; i>=0; i--)  
  {  
    bool is0 = (number & pow(2,i)) == 0;  
    if (is0)  
    {  
      cout<<'0';  
    }  
    else  
    {  
      cout<<'1';  
    }  
  }   

  cout<<endl;  

}

Upvotes: 1

back2dos
back2dos

Reputation: 15623

I am not sure this helps, plus it is just some weird pseudocode, but this should give you the desired ouput.

permutation (prefix, ones, zeros, cur) {
    if (ones + zeros == 0) output(cur);
    else {
        if (cur != -1) prefix = concat(prefix,cur);
        if (ones > 0) permutation(prefix, ones - 1, zeros, 1);
        if (zeros > 0) permutation(prefix, ones, zeros - 1, 0);
    }        
}

permutation(empty, 3, 2, -1);

greetz
back2dos

Upvotes: 0

foo
foo

Reputation: 2121

Homework and recursive algorithm? OK, here you go:

Base case: You have two elements, name them "a" and "b" and produce the concatenations ab, then ba.

Step: If your second Element is longer than 1, split it up in first field/letter and the other part, and pass that recursively as parameters to the function itself.

That will work for any strings and arrays.

Upvotes: 1

aib
aib

Reputation: 46991

What you want is actually a combination since the 1's and 0's are indistinguishable and therefore their order doesn't matter (e.g. 1 1 1 vs 1 1 1).

I recently had to rewrite a combination function myself because my initial version was written recursively in a very straightforward way (pick an element, get all the combinations of the remaining array, insert the element in various places) and did not perform very well.

I searched StackOverflow and just seeing the pictures in this answer lit up the iconic lightbulb over my head.

Upvotes: 2

Nabb
Nabb

Reputation: 3494

You can split up the combinations into those starting with 1 (n-1, k-1) and those starting with 0 (n-1, k).

This is essentially the recursive formula for the choose function.

Upvotes: 5

fredoverflow
fredoverflow

Reputation: 263250

Just start with 00111 and then use std::next_permutation to generate the rest:

#include <algorithm>
#include <iostream>
#include <string>

int main()
{
    std::string s = "00111";
    do
    {
        std::cout << s << '\n';
    }
    while (std::next_permutation(s.begin(), s.end()));
}

output:

00111
01011
01101
01110
10011
10101
10110
11001
11010
11100

Upvotes: 9

Related Questions