Python: Determine when more than one bit has changed in a nested list

Question:

Basically I have a list that goes like this:

[(0, 0, 1), 1]
[(0, 1, 0), 1]
[(0, 1, 0), 1]
[(0, 1, 1), 0]
[(0, 1, 1), 0]
[(1, 0, 0), 0]
[(1, 0, 0), 0]
[(1, 0, 1), 0]
[(1, 0, 1), 0]
[(1, 1, 0), 0]
[(1, 1, 0), 0]

And I want to compare the first element of the list with the next. If one of the elements has changed more than one bit, for example list[2] to list[3], i want my code to return both. I cant figure it out how to do it.

Asked By: Artur Correia

||

Answers:

The task of determining if more than one bit has changed can be done by:

  1. Calculating the XOR of value 1 and value 2.
  2. If the XOR of the values is not a power of two, more than one bit has been changed, e.g. (x & (x - 1)), where the XOR value is x.

For example:

for idx, (b1, b2) in enumerate(zip(data, data[1:])):
    a = int(''.join(map(str, (*b1[0], b1[1]))), 2)
    b = int(''.join(map(str, (*b2[0], b2[1]))), 2)
    if (a ^ b) & ((a ^ b) - 1):
        print(f'Change in index {idx} and {idx+1}', b1, b2)

gives the following output:

Change in index 0 and 1 [(0, 0, 1), 1] [(0, 1, 0), 1]
Change in index 2 and 3 [(0, 1, 0), 1] [(0, 1, 1), 0]
Change in index 4 and 5 [(0, 1, 1), 0] [(1, 0, 0), 0]
Change in index 8 and 9 [(1, 0, 1), 0] [(1, 1, 0), 0]

Comments:

This operation was made tricky by the fact of the first set of bits are nested within a tuple, and the final bit is not. This is the reason for the ‘ridiculous’ derivation of the a and b variables, to convert the nested bits into a base-2 integer value.


Edit:

Added additional logic to address the comment:

If I want to see if only one bit changed what I should do?

The logic is very similar, however has a key difference as the result of a single change and a non-change (using x & (x-1)) have the same value: 0. Therefore we must:

  1. Test a change has occurred.
  2. Verify the change has only affected a single bit.

For example:

for idx, (b1, b2) in enumerate(zip(data, data[1:])):
    a = int(''.join(map(str, (*b1[0], b1[1]))), 2)
    b = int(''.join(map(str, (*b2[0], b2[1]))), 2)
    xor = a ^ b
    if (xor) and not (xor & (xor - 1)):
        print(f'Change in index {idx} and {idx+1}', b1, b2)

The statement if (xor) and not (xor & (xor - 1)) tests there was a change (xor) (using truth value testing) and the change affects only a single bit (not (xor & (xor - 1))).

Output:

Change in index 6 and 7 [(1, 0, 0), 0] [(1, 0, 1), 0]
Answered By: S3DEV
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.