AdSense

Showing posts with label Bitwise operation. Show all posts
Showing posts with label Bitwise operation. Show all posts

Sunday, March 29, 2015

Minimum bits required to send a sequence of a deck of cards


Consider the 52 cards of a deck. You generated a random sequence for these cards and want to send that sequence to a receiver. You want to minimize the communication between you and the receiver, i.e., minimize the number of bits required to send the sequence.
What is the minimum number of bits required to send the sequence?
Hint: It is not 6 x 52
So first, how to come up with 6 * 52? Each card is in the range 1 - 52, so if we use 6 bits, there are 2^6 = 64 possibilities, which can cover all possible sequences.

Now we know that the bits required must include all possible sequences of that 52 cards, so how many possibilities? (52!). This means that we need n bits that 2^n >= (52!), so the theoretical answer is that we need log2(52!) = 226 bits.

So how to get that limit?

The first approach( besides the 6 * 52 one):
We know that the first card has 52 possibilities, the second has 51, ..., the 20th has 33 possibilities, so for the first 20 cards, we need at least 6 bits for each.
Then the 21st has 32 possibilities, ... 36th has 17 possibilities, so the next 16 cards we need at least 5 bits.
Then the next 8 cards we need 4 bits.
Then 4 cards, 3 bits.
Then 2 cards, 2 bits.
Then 1 card, 1 bit.
And after we know 51 cards, we know what the 52th is, so we don't need any bits. Thus in total:

20 * 6 + 16 * 5 + 8 * 4 + 4 * 3 + 2 * 2 + 1 = 249 bits. This solution is still larger.

The second one:
Consider we first send out k cards, which needs at most log2(Permu(k, 52)) bits, and now we have 52 - k cards. So we compute from 1 to 52 the k that can give us the minimum total bits required. We use recursion. Moreover, at each calling, the smaller number is already calculated, so we use an array to store at each n, the minimum bits required, thus can reduce some recursions.

However, Java has some problems with rounding (e.g., permu(1, 6) should return 3, but I get 4), so I cannot reach the optimized solution. See here for the C++ solution that can get to 227 bits.


public class SendingCards {
 static int N = 52;
 //Given n cards, best number of cards sent
 //static int[] cardsSent = new int[N + 1];
 static int[] minBits = new int[N + 1];
 static{
  minBits[1] = 0;
  minBits[2] = 1;
  minBits[3] = 3;
  //given 2 cards, sent 1 card first
  //cardsSent[1] = 1;
  //cardsSent[2] = 1;
  //cardsSent[3] = 3;
  
 }
 public static double logFact(int n){
  if(n == 0)
   return 0;
  double rst = 0;
  for(int i = 1; i <= n; i++)
   rst += Math.log((double)n) / Math.log(2.0);
  return rst;
 }
 public static double logPerm(int k, int n){
  //System.out.format("%d, %d: %.4f\n", k, n, logFact(n) - logFact(n - k));
  return logFact(n) - logFact(n - k);
 }
 //maxSent can be changed, after certain recursions, the number should converge
 //so we don't need to calculate from 1 to 52
 public static int send(int n, int maxSent){
  if(n <= 1)
   return 0;
  if(n == 2)
   return 1;
  if(n == 3)
   return 3;
  //if minBits have been calculated before, return the previous solution
  if(minBits[n] > 0)
   return minBits[n];
  int min = Integer.MAX_VALUE;
  int bits = 0;
  int kmin = 0;
  
  for(int k = 1; k <= Math.min(maxSent, n); k++){
   bits = (int)Math.ceil(logPerm(k, n)) + send(n - k, maxSent);
   if(min > bits){
    min = bits;
    kmin = k;
   }
  }
  System.out.println("n: " + n + ", min: " + min);
  //cardsSent[n] = kmin;
  minBits[n] = min;
  return min;
  
 }
 public static void main(String[] args) {
  System.out.println(send(N, 16));

 }

}

Friday, January 9, 2015

Divide Two Integers

So no multiplication, no division, nor mod. What is the only option? Bitwise operation!

For any integer, or long, "<< n" means multiply by 2 ^ n. And ">> n" means divide by 2 ^ n.


dividend = 45, divisor = 7
shift = 3, 7 * 2 * 2 * 2 = 56 > 45, the number of 7 that add up to be larger than 56 is 2 * 2 * 2 = 8
ans = 2 * 2 = 4,  a = 45 - 7 * 2 * 2= 17
shift = 2, 7 * 2 * 2 = 28 > 17,
ans = 4 + 2 = 6,  a = 17 - 7 * 2 = 3 < divisor

Note that since it is possible to overflow, we need to convert both dividend and divisor to long. ans should also be long type.


Update 2016-05-23:
45 ~ 7 * 6 = 7 * (2^2 + 2 ^ 1).

public int divide(int dividend, int divisor) {
        if (divisor == 0)
            return Integer.MAX_VALUE;
        boolean isNegative = (dividend > 0 && divisor < 0) ||
            (dividend < 0 && divisor > 0);
        long a = Math.abs((long)dividend);
        long b = Math.abs((long)divisor);
        if (a < b)
            return 0;
        long ans = 0;
        while (a >= b) {
            int shift = 0;
            while ((b << shift) <= a) 
                shift++;
            ans += ((long)1 << (shift - 1));
            a = a - (b << (shift - 1));
        }
        if (!isNegative && ans > (long)Integer.MAX_VALUE)
            return Integer.MAX_VALUE;
        return isNegative ? (int)-ans : (int)ans;
    }

Tuesday, December 30, 2014

All about bit manipulation


Check if a string has all unique characters


public boolean isUnique(String s) {
  if (s == null)
   throw new NullPointerException("Null string!");
  if (s.length() == 0)
   return true;
  int check = 0;
  for (int i = 0; i < s.length(); i++) {
   int val = Character.getNumericValue(s.charAt(i));
   if ((check & (1 << val)) > 0) 
    return false;
   check |= (1 << val);
  }
  return true;
 }

Insert bits

You are given two 32-bit numbers, N and M, and two bit positions, i and j.Write a method to set all bits between i and j in N equal to M (e.g., M becomes a substring of N located at i and starting at j).

Set all positions after j to zero
Set all positions after i back to 1
get the mask where all bits between i to j is cleared
put m into n from ith position

public int insertBitnumber(int m, int n, int posi, int posj) {
  //32 bit of 1s == -1;
  int max = ~0;
  /* e.g., posj = 3
   * 1 << posj = 1000
   * (1 << posj) - 1 = 111
   * max - that will leave all bits after j = 0;
   */
  int left = max - ((1 << posj) - 1);
  int right = (1 << posi) - 1;
  //this operation will leave all positions between posi and posj equals zero
  int mask = left | right;
  //mask & n will clear all bits between i and j in n
  // then we put m in those positions
  return (mask & n) | (m << posi);
  
 }


Decimal To Binary

Given a (decimal - e.g.3.72) number that is passed in as a string, print the binary representation.If the number can not be represented accurately in binary, print “ERROR” . 

Given an binary integer, we know that 1001 = 1 * 2^ 3 + 0 * 2 ^ 2 + 0 * 2 ^ 1 + 1 * 2^0 = 9. So if we keep doing mod operation and divide the number by 2, we can get the binary representation of the integer.
Analogously, 0.101 = 1 * (1/2)^1 + 0 * (1/2)^2 + 1 * (1/2)^3 = 0.625. Thus if we multiply the number by 2, we get 1 * (1/2)^0 + 0 * (1/2)^1 + 1 * (1/2)^2 = 1.25(10)  = 1.01(2). So if the result is greater than 1, we know that there should be 1 follows "." in the decimal part. We can do the same operation for every digit.


public class DecimalToBinary {
 public String decimalToBinary (String s) {
  if (s == null) 
   throw new NullPointerException("Null string");
  int intPart = Integer.parseInt(s.substring(0, s.indexOf('.')));
  double deciPart = Double.parseDouble(s.substring(s.indexOf('.')));
  
  String rst = "";
  while (intPart > 0) {
   rst = String.valueOf(intPart % 2) + rst;
   intPart >>= 1;
  }
  rst += ".";
  String decim = "";
  while (deciPart > 0) {
   if (decim.length() > 32) {
    return "Error";
   }
   if (deciPart == 1) {
    decim += "1";
    break;
   }
   double d = deciPart * 2;
   if (d >= 1) {
    decim += "1";
    deciPart = d - 1;
   }
   else {
    decim += "0";
    deciPart = d;
   }
  }
  return rst + decim;
 }

}

Next Largest and Smallest number that has the same number of 1 bits

Given an integer, print the next smallest and next largest number that have the same number of 1 bits in their binary representation.

Ok, this is interesting. So basically, given a binary number, 11100110, if we want to find the next largest one that has the same number of 1 bits, we first switch the first 0 to 1, which gives us 11101110, then we switch the next 1 after that 0 to 0, and results in 11101010. Since we want the next largest, we would want to  shift all the 1s after that to the most right side, and the result is: 11101001, yep, here is the solution.

The next smallest number is similar. Reversely, we switch the first 1 to 0 and the next 0 to 1. Using another example 110011 would result in 101011, and shifts, and the answer is: 101110.


public class NextBitNumber {
 private int setBit(int n, int index, boolean toOne) {
  int rst;
  if (toOne)
   rst = n | (1 << index);
  else {
   int mask = ~ (1 << index);
   rst = n & mask;
  }
  return rst;
 }
 private boolean getBit(int n, int index) {
  return (n & (1 << index)) > 0;
 }
 public int nextLargest(int n) {
  if (n <= 0)
   return -1;
  int index = 0;
  int countOnes = 0;
  while (!getBit(n, index))
   index++;
  while(getBit(n, index)) {
   index++;
   countOnes++;
  }
  n = setBit(n, index, true);
  index--;
  n = setBit(n, index, false);
  countOnes--;
  index--;
  for (int i = index; i > index - countOnes; i--) 
   n = setBit(n, i, false);
  for (int i = 0; i < countOnes; i++)
   n = setBit(n, i, true);
  return n;
 }
 public int nextSmallest(int n) {
  if (n <= 0)
   return -1;
  int index = 0;
  int countZeros = 0;
  while (getBit(n, index)) {
   index++;
  }
  while (!getBit(n, index)) {
   index++;
   countZeros++;
  }
  n = setBit(n, index, false);
  index--;
  n = setBit(n, index, true);
  index--;
  countZeros--;
  for (int i = index; i > index - countZeros; i--)
   n = setBit(n, i, true);
  for (int i = 0; i < countZeros; i++)
   n = setBit(n, i, false);
  return n;
 }

}

What does (n & (n - 1)) == 0 used for? 

Check if n == 0 or power of 2!
For example, 100 and 11;

Bits needed to convert a number to another number

Write a function to determine the number of bits required to convert integer A to integer B.
Input: 31, 14
Output: 2 

Count the number of different bits in a number by using XOR.


public class BitsNeededToConvert {
 public int bitsNeeded(int a, int b) {
  if (a == b)
   return 0;
  int count = 0;
  for (int c = a ^ b; c >= 0; c = c>> 1) {
   count += c & 1;
  }
  return count;
 }

}


Something about Hexadecimal

In Unix shells, and C programming language:
prefix 0x for numeric constants represented in hex. e.g., 0x5A3 (144310).
Character and string constants may express characters codes in hexadecimal with the prefix \x followed by two hex digits: \x1B (Esc control character)
Unicode standard:
A character value is represented with U+ followed by the hex value, e.g., U+20AC (euro sign)

Convert hexadecimal to binary

Swap odd and even bits in a number

Write a program to swap odd and even bits in an integer with as few instructions as possible (e.g., bit 0 and bit 1 are swapped, bit 2 and bit 3 are swapped, etc).

shift all odd bits left for 1 position and shift all even bits right for 1 position

public class SwapBits {
 public int swapBits (int n) {
   //0xaaaaaaaa = 10101010...10
   // 0x55555555 = 1010101...01
   return (n & 0xaaaaaaaa) >> 1 | (n & 0x55555555) << 1;
 }
}

Monday, December 15, 2014

Single number I & II &III

Single Number

Given an array of integers, every element appears twice except for one. Find that single one.

Bitwise operations.

Single number I
Using XOR operation. Because each number appears twice, XOR cancels out them except the single number.

public class SingleNumber {
    public int singleNumber(int[] A) {
        int rst = 0;
        for (int i = 0; i < A.length; i++)
            //XOR
            rst ^= A[i];
        return rst;
        
    }
}

Single Number II

Given an array of integers, every element appears three times except for one. Find that single one.

Count each of the 32 bit of every element. Then mod each bit by 3, this operation will cancels out all numbers that appear three times.

Update: 2015 - 01 - 03

I put the array iteration at the outer loop at first, then I realize it will need an extra iteration to do the mod and add bits back.
Loop the bits first allows us to get the result in one pass.

public class Solution {
    public int singleNumber(int[] A) {
        if (A == null || A.length == 0)
            return -1;
        //unsigned int, 32 bits
        int[] bits = new int[32];
        int rst = 0;
        for (int i = 0; i < 32; i++)
        {
            for (int j = 0; j < A.length; j++)
            {
                // & 1 will count only the bit 1
                bits[i] += A[j] >> i & 1;
                bits[i] %= 3;
            }
            //adding back to the original position by left shift i bits. 
            //e.g.  000 = 000 || (1 << 2) = 100
            rst |= (bits[i] << i);
        }
        return rst;
        
    }
}

Single Number III

Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.
For example:
Given nums = [1, 2, 1, 3, 2, 5], return [3, 5].
Note:
  1. The order of the result is not important. So in the above example, [5, 3] is also correct.
  2. Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?


Similar to the first problem, we use xor. Now after the first traversal, we have a number n that is the xor of the two single numbers. We then try to find the first different bit from the number. Then we traverse the array again, now we xor all numbers with that bit equals 1, for all numbers that appear twice, they will be cancel out. This operation will also cancel one of the two single numbers with that bit equals 1. Now the rest of n is the first number and we use xor to find the second number.


    public int[] singleNumber(int[] nums) {
        int[] rst = new int[2];
        if (nums == null || nums.length < 2)
            return rst;
        int xor = 0;
        for (int n : nums) 
            xor ^= n;
        
        int first_different_bit = 0;
        for (first_different_bit = 0; first_different_bit < 32; first_different_bit++) {
            if (((xor >> first_different_bit) & 1) == 1)
                break;
        }
        
        int num1 = 0;
        for (int n : nums) {
            if (((n >> first_different_bit) & 1) == 1)
                num1 ^= n;
        }
        rst[0] = num1;
        rst[1] = xor ^ num1;
        return rst;
    }