Saturday, December 17, 2011

Next higher Number with same number of SET BITS

Given a number x, find next number with same number of 1 bits in it’s binary representation.
For example, consider x = 12, whose binary representation is 1100 (excluding leading zeros on 32 bit machine). It contains two logic 1 bits. The next higher number with two logic 1 bits is 17 (100012).

1st Approach:

Given a number m find the next higher number r , that has same number of 1-bits.

* Ex : 3 (0000011) => 5(0000101)

* 6(0000110) => 9(0001001)

* 11(0001011) => 13(0001101)

* 23(0010111) => 27(0011011)

* 24(0011000) => 33(0100001)

* 44(0101100) => 49(0110001)

* 46(0101110) => 51(00110011)

1st Thinking(Algorithm)
1.count number of set bits in given number .
2. start from that number in loop & count number of set bits in all number > n untill we found the same set bits in any number, once found stop.

but problem with this algorithm is that it will take too much time for bignumber
O(N) where N is number of iteration untill we find number > N with same number of set bits.

2nd Solution (Most Optimized)

# Observations I

* Look at the input and the outputs again and see if you can make some algorithm out of it

* 3 (0000011) => 5(0000101)

* 6(0000110) => 9(0001001)

* 11(0001011) => 13(0001101)

* 23(0010111) => 27(0011011)

* 24(0011000) => 33(0100001)

* 44(0101100) => 49(0110001)

* 46(0101110) => 51(00110011)


# Observations II

* Hint : Now concentrate on the highlighted parts of input

* 3 (0000 011 ) => 5(0000 101 )

* 6(000 0110 ) => 9(000 1001 )

* 11(0001 011 ) => 13(0001 101 )

* 23(001 0111 ) => 27(001 1011 )

* 24(0 011000 ) => 33(0 100001 )

* 44(01 01100 ) => 49(01 10001 )

* 46(01 01110 ) => 51(01 10011 )

# Observations III

* As you can see,

o the non-highlighted part is same in i/p and o/p as well

o And the highlighted part is consecutive 1’s from the least-significant side (right hand side)

* 3 (0000 011 ) => 5(0000 101 )

* 6(000 0110 ) => 9(000 1001 )

* 11(0001 011 ) => 13(0001 101 )

* 23(001 0111 ) => 27(001 1011 )

* 24(0 011000 ) => 33(0 100001 )

* 44(01 01100 ) => 49(01 10001 )

* 46(01 01110 ) => 51(01 10011 )

# Observations IV

* As you can see, the non-highlighted part is same in i/p and o/p as well

* 3 (0000 011 ) => 5(0000 101 )

* 6(000 0110 ) => 9(000 1001 )

* 11(0001 011 ) => 13(0001 101 )

* 23(001 0111 ) => 27(001 1011 )

* 24(0 011000 ) => 33(0 100001 )

* 44(01 01100 ) => 49(01 10001 )

* 46(01 01110 ) => 51(01 10011 )

# Observations V

* Now lets just look at what changed

* 011 => 101

* 0110 => 1001

* 011 => 101

* 0111 => 1011

* 011000 => 100001

* 01100 => 10001

* 01110 => 10011

* Do you see a pattern?

# Observations VI

* Yes, as you have rightly observed, left hand side is :

o A 0 followed by

o One or more 1’s (say x) followed by

o Zero or more 0’s (say y)

* Is changed to

o A 1 followed by

o (y+1) zeroes followed by

o (x-1) 1’s

* 0 11 => 1 0 1

* 0 11 000 => 1 0 000 1

Algorithm

# Now let’s frame the algorithm

* Given a bit-pattern, start from right, find successive zeroes (xxxx01111 0000 )

* Followed by zeroes find successive 1’s (xxxx0 1111 0000 )

* Stop on hitting a zero (xxxx 0 1111 0000 )

* Interchange/swap that zero with a 1 from successive 1’s (xxxx 1 0 111 0000 )

* Now move the remaining 1’s to extreme right, filling the gap with zeroes (xxxx 1 0 0000 111 )

# Doing it programatically in C

* unsigned snoob(unsigned x) {

o unsigned smallest, ripple, ones;

o // x = xxx0 1111 0000

o smallest = x & -x; // 0000 0001 0000------------remove all ones except the right most

o ripple = x + smallest; // xxx1 0000 0000 ------Swap the 1 and zero

o ones = x ^ ripple; // 0001 1111 0000-----------

o ones = (ones >> 2)/smallest; // 0000 0000 0111

o return ripple | ones; // xxx1 0000 0111

* }

Working Code:

#include<stdio.h>

using namespace std;

typedef unsigned int uint_t;

// this function returns next higher number with same number of set bits as x.
uint_t snoob(uint_t x)
{

uint_t rightOne;
uint_t nextHigherOneBit;
uint_t rightOnesPattern;

uint_t next = 0;

if(x)
{

// right most set bit
rightOne = x & -(signed)x;

// reset the pattern and set next higher bit
// left part of x will be here
nextHigherOneBit = x + rightOne;

// nextHigherOneBit is now part [D] of the above explanation.

// isolate the pattern
rightOnesPattern = x ^ nextHigherOneBit;

// right adjust pattern
rightOnesPattern = (rightOnesPattern)/rightOne;

// correction factor
rightOnesPattern >>= 2;

// rightOnesPattern is now part [A] of the above explanation.

// integrate new pattern (Add [D] and [A])
next = nextHigherOneBit | rightOnesPattern;
}

return next;
}

int main()
{
int x = 156;
cout<<"Next higher number with same number of set bits is "<
getchar();
return 0;
}

Time Complexity O(1)
Space Complexity O(1)

More Example:

The Algorithm Flow:
x = 15610
x = 10011100(2)
10011100
00011100 - right most string of 1's in x
00000011 - right shifted pattern except left most bit ------> [A]
00010000 - isolated left most bit of right most 1's pattern
00100000 - shiftleft-ed the isolated bit by one position ------> [B]
10000000 - left part of x, excluding right most 1's pattern ------> [C]
10100000 - add B and C (OR operation) ------> [D]
10100011 - add A and D which is required number 163(10)

C Code:

uint_t snoob(uint_t x)
{
  uint_t rightOne;
  uint_t nextHigherOneBit;
  uint_t rightOnesPattern;
  uint_t next = 0;
  if(x)
  {
       rightOne = x & -(signed)x;// right most set bit
    // reset the pattern and set next higher bit
    // left part of x will be here
    nextHigherOneBit = x + rightOne;
    // nextHigherOneBit is now part [D] of the above explanation.
    rightOnesPattern = x ^ nextHigherOneBit;// isolate the pattern
    rightOnesPattern = (rightOnesPattern)/rightOne;// right adjust pattern
    rightOnesPattern >>= 2;  // correction factor
    // rightOnesPattern is now part [A] of the above explanation.
    // integrate new pattern (Add [D] and [A])
    next = nextHigherOneBit | rightOnesPattern;
  }
  return next;
}

Variation:
Create 32 Bit numbers (signed or unsigned doesn't matter, the highest bit will never be set anyway) and each number must have a given number of Bits set


Reference:
http://stackoverflow.com/questions/506807/creating-multiple-numbers-with-certain-number-of-bits-set
http://stackoverflow.com/questions/7451922/bitwise-shift-to-generate-all-possible-permutations-in-c?lq=1

1 comment: