Connecting Tech Pros Worldwide Forums | Help | Site Map

k-element subsets

Newbie
 
Join Date: Dec 2007
Posts: 16
#1: Dec 23 '08
Hi,
The aim of this C++ code is to print all the k-element subsets of a set of size n. But somewhere it goes wrong - it doesn't print the answer properly. I tried a lot to find the mistake, but in vain. Please help me in debugging it and thanks in advance.

Expand|Select|Wrap|Line Numbers
  1. #include<iostream>
  2. #include<vector>
  3. using namespace std;
  4.  
  5. int main()
  6. {
  7.     printf( "Enter the number of elements of the set:\n" );
  8.     int n;
  9.     scanf( "%d", &n );
  10.     printf( "Enter the elements of the set:\n" );
  11.     vector<int> v( n );
  12.     for( int i = 0; i < n; i++ )
  13.     scanf( "%d", &v[i] );
  14.     printf( "Enter the length K which is the length of the subsets to be printed: \n" );
  15.     int k;
  16.     scanf( "%d", &k );
  17.     int s = ( 1 << k ) - 1;
  18.     while( !( s & ( 1 << n ) ) )
  19.     {
  20.     printf( "\n" );
  21.     for( int i = v.size() - 1; i >= 0; i-- ) 
  22.     {
  23.         if( (s & (  1 << i )) != 0 )
  24.         {
  25.         printf( "%d ", v[i] );
  26.         }
  27.         int lo = s & ~( s - 1 ); // last one bit
  28.         int lz = ( s + lo ) & ~s; //last zero bit above lo
  29.         s |= lz; // setting the bit
  30.         s &= ~( lz - 1 ); // clearing bits below lz
  31.         s |= ( lz >> ffs(lo) ) - 1; // adding proper number of bits at the end
  32.     }
  33.     }
  34.     printf( "\n" );
  35.     return 0;
  36. }
  37.  
  38.  

JosAH's Avatar
Expert
 
Join Date: Mar 2007
Posts: 10,611
#2: Dec 23 '08

re: k-element subsets


You can do much better than that; basically you want C(n, k) n >= k; the numbers make up the index values of the elements of your set. The following function computes the next combination (lexicographically) given a current sequence of k numbers out of a set of n. If no such combination can be found anymore it'll return false otherwise true is returned. Have a look:

Expand|Select|Wrap|Line Numbers
  1. int combine(int* c, int k, int n) {
  2.  
  3.     for (int i= k; --i >= 0;) {
  4.         if (++c[i] <= n-(k-i)) {
  5.             while (++i < k)
  6.                 c[i]= c[i-1]+1;
  7.             return 1;
  8.         }
  9.     }
  10.     return 0;
  11. }
  12.  
kind regards,

Jos
Reply