Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java manipulating large bit numbers

Tags:

java

I have been working on the Interview Street challenge Changing Bits in my spare time for a little over a week now and just spinning my wheels at this point so I am hoping someone might be able to give me a pointer or hint in the right direction.

The basics of the challenge is taking two bit strings A & B and running a number of queries manipulating the two bit strings.

Let A and B be two N bit numbers. You are given initial values for A and B, and you should write a program which processes three kinds of queries:

  • set_a idx x: Set A[idx] to x, where 0 <= idx < N, where A[idx] is idx'th least significant bit of A.
  • set_b idx x: Set B[idx] to x, where 0 <= idx < N.
  • get_c idx: Print C[idx], where C=A+B, and 0<=idx

Where the bit numbers are length 1 to 100,000 and the program can have between 1 to 500,000 queries of any combination of set_a, set_b, or get_c.

To minimize looping I am using C as a running total. When a bit in A or B changes, the changed bit is also added or subtracted, from C. Further minimizing looping when adding and subtracting is done from the changed bit to left hand while there is still a carry bit.

private static void add(final boolean[] the_array, final int the_index)
{
    for(int iter = the_array.length - the_index - 1; iter >= 0; iter--)
    {
        if(the_array[iter])
        {
            the_array[iter] = false;
        }
        else if(!the_array[iter])
        {
            the_array[iter] = true;
            return ;
        }
    }
}

private static void subtract(final boolean[] the_array, final int the_index)
{
    for(int iter = the_array.length - the_index - 1; iter >= 0; iter--)
    {
        if(the_array[iter])
        {
            the_array[iter] = false;
            return ;
        }
        else if(!the_array[iter])
        {
            the_array[iter] = true;
        }
    }
}

Overall the program runs pretty well completing the worst edge case of bit length of 100,000 and 500,000 queries runs in about 120ms but it is still not fast enough for the purposes of the challenge. Due to the size of the bit length quickly exceeds the primitive integer (long as well) values in Java so most of the API is not applicable for this. As I am not making much progress increasing the overall run time magnitude is starting to suggest there might be an algorithm or data structure that is better suited for this than just an array. Any thoughts?

like image 812
ntin Avatar asked Feb 18 '12 04:02

ntin


1 Answers

Hmm, off the top of my head:
Don't keep C around / updated, just calculate the bit you're asked for on the fly. Remember that when you add the corresponding bit positions of A and B, you only need to look down the adjacent less-significant bits until you find a point where they're both zero - anything beyond that can't carry bits past it. e.g.

A: 001101001010111
B: 010110100010110
     ^ asked for C there
   1000111^ only need to add bits from here
     ^ until you get your answer.
like image 88
tzaman Avatar answered Oct 03 '22 13:10

tzaman