bit function

Let f(k) = y where k is the y-th number in the increasing sequence of non-negative integers with the same number of ones in its binary representation as y, e.g. f(0) = 1, f(1) = 1, f(2) = 2, f(3) = 1, f(4) = 3, f(5) = 2, f(6) = 3 and so on. Given k >= 0, compute f(k).

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;
}


No comments: