0
$\begingroup$

Assume we have some (for example 10 different) 8 bit numbers and a specific target number (also 8 bit) is there an efficient algorithm to find out which and if any combination of source numbers XORed together result in the target number. And if there are multiple solutions.

How could I solve such problems (without trying all possible combinations) and is there a name for this kind of problem.

Thanks in advance

4 Answers 4

0

Although I don't know any terms for this class of problem. Since XOR behaves slightly differently than addition, it is possible to break up the problem and make it solvable more easily than brute-force by focusing on one bit at a time.

Create a storage array at least the size of your bit-width; values will be stored in the array such that the n-th element (in a 1-indexed array) has the n-th bit as its most-significant bit (MSB). For each of the inputs (I'll refer to them ask masks), see if a value is stored with the same MSB set, and if so, XOR the values; this will clear out the MSB and result in a smaller number. Continue until no numbers stored have the same MSB set, then store the number. Numbers that result in a zero from this operation are redundant (eg with 13 and 5 stored, 8 is redundant since 8 = 13 xor 5).

Below is an implementation in Python 3 to see if it is possible to obtain a target given a number of masks. It does not currently report which of the input masks were used as the current version doesn't retain them. Try it on repl.it

def xor_combo(target, mask_list):
    masks_by_bit = [0] * 8 # number of bits
    # use defaultdict(int) for arbitrary size

    for mask in mask_list:
        # https://docs.python.org/3/library/stdtypes.html#int.bit_length
        while masks_by_bit[mask.bit_length() - 1] != 0:
            mask ^= masks_by_bit[mask.bit_length() - 1]
        if mask != 0:
            masks_by_bit[mask.bit_length() - 1] = mask
        # else: redundant mask

    while masks_by_bit[target.bit_length() - 1] != 0:
        target ^= masks_by_bit[target.bit_length() - 1]
    return (target == 0)

Example output:

xor_combo(5, [7, 2])

True : since 5 = 7 xor 2

xor_combo(5, [7, 3, 4])

False : since no combination 7, 3, and 4 can be combined via xor to give 5

xor_combo(5, [7, 3, 1])

True : since 5 = 7 xor 3 xor 1

1

I am not really sure if this is the best way to solve your problem, but this is the way I would do it. I would go through all the numbers in given set and XOR every one of them with the target number. If the result of this operation is also in the given set then those two numbers make one pair which XORed results in the target number. I hope that was somewhat clear.

  • 0
    That's a nice way to find out if there are two numbers that do the job. Note that if you get $0$ the target number was in the set. To check for three you could use the numbers you get this way as a new group of targets to try to match from the the original set, and so on.2017-02-18
  • 0
    My concrete numbers are just examples. In practice the set will be greater than 100 and the result will almost always be a combination of at least 20 numbers.2017-02-18
0

Viewing your $n$-bit numbers as bit vectors, they form a vector space over $\mathbb F_2$ (the field with two elements) -- addition is binary XOR, and multiplication is binary AND.

Viewed, this way, you have a number of vectors and want to express a given vector as a linear combination of the given ones. Your specification is an XOR of some of the given vectors, but XOR is just a sum in this vector space, and since the only possible nonzero coefficient in $\mathbb F_2$ is $1$, a sum is the same as a linear combination.

This means that what you have is just a standard linear vector/matrix equation over $\mathbb F_2$, and standard techniques from linear algebra, such as Gaussian elimination, will work.

If you have $10$ original vectors, since that is more than $8$, ordinary linear algebra tells us that there will always be either no solutions, or more than one possible solution.

0

I did some research and as it turns out there is no faster way than trying all possible combinations. The problem is an NP-hard problem. Here is an Wikipedia article basicly describing the same problem (and possible solutions): https://en.wikipedia.org/wiki/Subset_sum_problem

  • 1
    That problem is not the same; having XOR rather than $+$ makes a huge difference. Henning Makholm's answer is correct, and shows that your original problem is in P.2017-05-11