Analysis:
Ex:
// series with 2 bits
00000011 1
00000101 2
00000110 3
00001001 4
00001010 5
00001100 6
00010001 7
// series with 3 bits
00000111 1
00001011 2
00001101 3
00001110 4
00010011 5
//------------- PROBABLY NOT SO OPTIMAL ---------------
#include "stdio.h"
#include "stdlib.h"
/**
* O(n) algorithm, where n is the number of bits set
* This algorithm works on the fact that when 1 is subtracted,
* there exists a bit k, below which all the bit places get changed
* so, num & num-1 will clear all the bits below the bit k.
* ( to see this enable PrintBinary() function below )
* */
size_t CountBits(size_t num)
{
size_t count = 0;
while (num)
{
//PrintBinary(num);
num &= num-1;
++count;
}
return count;
}
/**
* This is O(1) algorithm, but uses a lookup table.
* Initially fill the lookup table with the bit count
* then look into it :)
* we can bring down the memory even further by using a lookup
* table of size 16 (4 bits instead of 8 )
* */
size_t lookup[256] = {};
void InitLookup()
{
for( int i = 0; i <= 0xFF; ++i)
lookup[i] = CountBits(i);
}
size_t CountBits_O1(size_t num)
{
size_t count = lookup[num&0xFF] +
lookup[ (num >> 8) & 0xFF ] +
lookup[ (num >> 16) & 0xFF ] +
lookup[ (num >> 24) & 0xFF ];
return count;
}
void FindInSeries(size_t k)
{
const size_t bit_count = CountBits_O1(k);
size_t seq_pos = 0;
// This is the start of the series
size_t start = ( 1 << bit_count ) - 1;
printf(" start %d, bit_count %d \n", start, bit_count );
for ( size_t i=start; i != k; ++i)
{
if ( CountBits_O1(i) == bit_count )
{
++seq_pos;
printf("%d ", i);
}
}
++seq_pos;
printf("\n f(%d) = %d \n", k, seq_pos);
}
int main (int argc, char* argv[])
{
size_t num = atoi( argv[1] );
InitLookup();
FindInSeries(num);
return 0;
}