2

I want to calculate XOR of numbers from 0 to (n)^{1/2} - 1 with each of numbers from 0 to (n)^{1/2} - 1. i want to do this in O(n) time and cant use the XOR, OR, AND operations.

If i know the XOR of X and Y, can i calculate XOR of X+1 and Y in constant time?

As some have pointed out that XOR can be calculated in constant time using AND and NOT. How do i do the same for AND? How do i calculate AND of numbers from 0 to (n)^{1/2} - 1 with each of numbers from 0 to (n)^{1/2} - 1. i want to do this in O(n) time and cant use the XOR, OR, AND operations.

P.S. - RAM model is being assumed here and operations (add, multiply, divide) on < log(n) bit numbers can be done is constant time.

11
  • Why can't you use xor? What operators are you allowed to use instead? Commented Feb 20, 2011 at 12:16
  • 1
    Is this "homework"? If yes, you should tag it accordingly. Commented Feb 20, 2011 at 12:25
  • The output contains O(n.log(n)) bits making it impossible to generate in O(n) time. Commented Feb 20, 2011 at 12:29
  • @Paul: How can the output contain O(n log n) bits? The highest number it's dealing with is root n... Commented Feb 20, 2011 at 12:30
  • @Jon root n contains log(root n) = log(n)/2 bits. The output's a table of sqrt(n) * sqrt(n) numbers (ie, n numbers) each with O(log n) bits. Commented Feb 20, 2011 at 12:31

5 Answers 5

2

Yes.

Start with a [1x1] grid:

H(-1) = [ 0 ]

Then apply the recursion:

H(i) = [ H(i-1)           H(i-1)+(1 << i)
         H(i-1)+(1 << i)  H(i-1)          ]

where that denotes matrix concatenation. i.e. each recursion doubles the size of the grid in each dimension. Repeat until you achieve the required size.

Sign up to request clarification or add additional context in comments.

2 Comments

Nice answer. I found a much more complicated way to do it.
@xanatos: Yes it works! I doubt it has a name! There's really not a lot of magic going on here; I'm simply calculating the XOR function independently for each bit position, and then spreading the results across all positions in the output array. (If you rewrite H(i-1) as H(i-1)+(0 << i) in my answer, it should perhaps make it more obvious why it works.)
2

You can build an XOR gate from NANDs (diagram here), so you could do it with an if statement with ! (NOT) and && AND (if we use C/C++/PHP as an example here). As for working it out in a constant time, the calculation is the same every iteration, so it will be constant.

1 Comment

I think the point is that this approach calculates results one bit at a time. There are n.log(n) bits in the output matrix, so this will not be O(n).
2

A XOR can be built using AND and NOT (and combining them to build a NAND). Can you use AND and NOT?

In C#:

Func<bool, bool, bool> nand = (p, q) => !(p && q);

Func<bool, bool, bool> xor = (p, q) =>
{
    var s1 = nand(p, q);
    var s2a = nand(p, s1);
    var s2b = nand(q, s1);
    return nand(s2a, s2b);
};

I'm mimicking this: http://en.wikipedia.org/wiki/NAND_logic#XOR

In C#, using modulus, sum and multiply. (Limits: I'm using uint, so max 32 bits. It will work for ulong, so max 64 bits)

uint a = 16;
uint b = 5;
uint mult = 1;
uint res = 0;

for (int i = 0; i < 32; i++)
{
    uint i1 = a % 2;
    uint i2 = b % 2;

    if (i1 != i2) {
        res += mult;
    }

    a /= 2;
    b /= 2;
    mult *= 2;
}

Where res is the response.

Modulus can be built on top of division, multiplication and subtraction.

7 Comments

I don't have any problem if someone doesn't like my reply, but whoever gave me a -1 should at least tell me what I did wrong. Yes, I do know that mine isn't a perfect solution, but considering that the OP is probably asking an "academic" or "homework" question, I don't think the response must be "the most beautiful in the world"
The problem is that your solution doesn't answer the question correctly. You have implemented xor using a bit-by-bit approach which yields an O(n.log(n)) solution. The question was to find an O(n) solution (although admittedly the question wasn't worded particularly clearly).
@Paul From what I read, (quoting) "and operations (add, multiply, divide) on < log(n) bit numbers can be done is constant time.", so each cycle of my for is constant time, I need to do n^1/2*n^1/2 xor == "n" xor, so my solution is O(kn) that is like O(n).
@xanatos you have a loop to 8. To work for all ints (rather than just for ints between 0 and 256), this has to be a loop to log(n).
@Paul Mine was an example. I'm even using uint, so it's max 32 bits. The question wasn't language-specific, and mine was a simple implementation. I'm quite sure the question was "homework", and it isn't something that will be used in the new Skynet :-) It's a "proof of concept". Oli Charlesworth solution is much better (but if I was a teacher, THIS solution I would believe that a random student could do it, Charlesworth's one? bwahahahaha)
|
1

if the two are not equal, then they are xor.

xorBits(bit1,bit2){
     return bit1 != bit2?1:0
}

xorBooleans(boolean1,boolean2){
    return boolean1 != boolean2
}

Comments

0

First, let k be the smallest power of 2 greater than or equal to sqrt(n). k is still O(sqrt(n)) so this won't change the complexity.

To construct the full k by k table, we construct it one row at a time.

We start with the 0th row: this is easy, because 0 xor j = j.

for i in xrange(k):
    result[0][i] = i

Next, we go over the rows in gray-code order. The gray-code is a way of counting every number from 0 to one-less than a power of 2 by changing one bit at a time.

Because of the gray-code property, we're changing the row number by 1 bit, so we have an easy job computing the new row from the old since the xors will only change by 1 bit.

last = 0
for row in graycount(k):
    if row == 0: continue
    bit_to_change = find_changed_bit(last, row)
    for i in xrange(k):
        result[row][i] = flip_bit(result[last][i], bit_to_change))
    last = row

We need some functions to help us here. First a function that finds the first bit that's different.

def find_changed_bit(a, b):
    i = 1
    while True:
        if a % 2 != b % 2: return i
        i *= 2
        a //= 2
        b //= 2

We need a function that changes a bit in O(1) time.

def flip_bit(a, bit):
    thebit = (a // bit) % 2
    if thebit:
        return a - bit
    else:
        return a + bit

Finally, the tricky bit: counting in gray codes. From wikipedia, we can read that an easy gray code can be obtained by computing xor(a, a // 2).

def graycount(a):
    for i in xrange(a):
        yield slow_xor(a, a // 2)

def slow_xor(a, b):
    result = 0
    k = 1
    while a or b:
        result += k * (a % 2 == b % 2)
        a //= 2
        b //= 2
        k *= 2
    return result

Note that the slow_xor is O(number of bits in a and b), but that's ok here since we're not using it in the inner loop of the main function.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.