How to replace the independent 1 with 0 in binary number using only bitwise operations?

Question:

By "independent 1" I mean 1 that has no other 1 next to it ("010" or "10" and "01" at the ends of the num.)
If the 1 doesn´t have any 1 next to it, it will change to 0.

For example:

11010 = 11000

10101 = 00000

1111 = 1111

I can´t use for or while loops. Only bitwise operators.

I tried something like this:

num = 0b11010
count = 0

if num & 1 == 1:
    if (num >> 1) & 1 == 1 or (num << 1) & 1 == 1:
        count += 1
else:
    count += 0

if (num >> 1) & 1 == 1:
    if (num >> 2) & 1 == 1 or (num >> 0) & 1 == 1:
        count += 2
else:
    count += 0
.
.
.
#(Same principle)

But the code will get too long when I try to implement it for bigger numbers.

Asked By: randomdomnar

||

Answers:

Maybe this code can give you some idea:

a = [3, 5, 8, 1, 2, 7]
b = [2, 6, 8]
lenA, lenB = len(a), len(b)
# Getting the absolute value of abs
diff = abs(lenA - lenB)
if lenA < lenB:
    # extend expands the list. will add an absolute value of zero to the end
    a.extend([0]*diff)
else:
    b.extend([0]*diff)
print(b)
Answered By: Ramazan Şen

This is a good exercise in bit shifting and bit comparison. One way this can be solved (there’s probably several different ways) is by storing a left shifted and right shifted version of the original number. From there, you can use the XOR function to detect which bits are different. If both neighbors of a 1 are 0, then the XORs (as shown below) will simultaneously be 1. At that point, we have the 1’s which are neighbored by two zeros. Then we can invert the value to highlight all the bits except for the bits we just found. Comparing that number with the original number with the AND function will ‘erase’ the bits from the original number.

It’s not so easy to explain this without visuals, so hopefully a look at the code will help in understanding. I’m assuming a 32-bit length here.

num = 0b11010

# Assume 32 bit, make sure only zeros are shifted in on either side
num_l1 = (num<<1)&(~0x1)  # make sure the new right bit is zero
num_r1 = (num>>1)&(~0x80000000)  # make sure the new left bit is zero

# Print the left and right shifted numbers along with num. As we can see, we
#  are looking for bits which are a 1 in the num, but a 0 in both left and right
#  shift.
print(f' Left Shifted Number: {"{:032b}".format((num<<1)&(~0x1))}')
print(f'              Number: {"{:032b}".format(num)}')
print(f'Right Shifted Number: {"{:032b}".format((num>>1)&(~0x80000000))}')

# XORing with left and right will highlight values that are either 010 or 101 in
#  the original num. We only want 010, so we then AND the new sequence with
#  the original num to only allow 010 sequences to pass.
find_lonely_ones = num & ((num^num_l1) & (num^num_r1))

# We can then invert the lonely bits and AND with the original num
new_num = num & (~find_lonely_ones)
print()
print(f'      Number: {"{:0b}".format(num)}')
print(f'Final Answer: {"{:0b}".format(new_num)}')


# We can print each step for clarification
print()
print(f' Left Shifted Number XOR Number: {"{:032b}".format(num^num_l1)}')
print(f'Right Shifted Number XOR Number: {"{:032b}".format(num^num_r1)}')
print(f'    AND of the above operations: {"{:032b}".format((num^num_l1) & (num^num_r1))}')
print(f'     The above value AND Number: {"{:032b}".format(find_lonely_ones)}')
print(f' NOT the above value AND Number: {"{:032b}".format(num & (~find_lonely_ones))}')
Answered By: greenerpastures