|
| 1 | +""" |
| 2 | +Swap two bits at given positions in a non-negative integer using bitwise operators. |
| 3 | +
|
| 4 | +Wikipedia reference: |
| 5 | +https://en.wikipedia.org/wiki/Bit_manipulation |
| 6 | +""" |
| 7 | + |
| 8 | + |
| 9 | +def swap_bits(number: int, i: int, j: int) -> int: |
| 10 | + """ |
| 11 | + Swap the bits at the position i and j (0-indexed from right side) |
| 12 | +
|
| 13 | + Arguments: |
| 14 | + number (int): Non-negative integer whose bits are to be swapped. |
| 15 | + i (int): Index of 1st bit to swap. |
| 16 | + j (int): Index of 2nd bit to swap. |
| 17 | +
|
| 18 | + Returns: |
| 19 | + int: Integer obtained after swapping of bits. |
| 20 | +
|
| 21 | + Raises: |
| 22 | + TypeError: If argument is not an Integer |
| 23 | + ValueError: Invalid argument or bit positions. |
| 24 | +
|
| 25 | + Examples: |
| 26 | + >>> swap_bits(28, 0, 2) # 11100 -> swap rightmost bits 0 and 2 |
| 27 | + 25 |
| 28 | + >>> swap_bits(15, 1, 2) # 1111 -> swapping the bits 1 and 2 |
| 29 | + 15 |
| 30 | + >>> swap_bits(10, 0, 3) # 1010 -> swap the bits 0 and 3 |
| 31 | + 3 |
| 32 | + >>> swap_bits(10.5, 0, 3) |
| 33 | + Traceback (most recent call last): |
| 34 | + ... |
| 35 | + TypeError: All arguments MUST be integers! |
| 36 | + >>> swap_bits(-5, 1, 3) |
| 37 | + Traceback (most recent call last): |
| 38 | + ... |
| 39 | + ValueError: The number MUST be non-negative! |
| 40 | + >>> swap_bits(10, -1, 2) |
| 41 | + Traceback (most recent call last): |
| 42 | + ... |
| 43 | + ValueError: Bit positions MUST be non-negative! |
| 44 | + """ |
| 45 | + if not all(isinstance(x, int) for x in (number, i, j)): |
| 46 | + raise TypeError("All arguments MUST be integers!") |
| 47 | + |
| 48 | + if number < 0: |
| 49 | + raise ValueError("The number MUST be non-negative!") |
| 50 | + |
| 51 | + if i < 0 or j < 0: |
| 52 | + raise ValueError("Bit positions MUST be non-negative!") |
| 53 | + |
| 54 | + # Extraction of Bits |
| 55 | + bit_first = (number >> i) & 1 |
| 56 | + bit_second = (number >> j) & 1 |
| 57 | + |
| 58 | + # If bits differ swap them |
| 59 | + if bit_first != bit_second: |
| 60 | + number ^= (1 << i) | (1 << j) |
| 61 | + |
| 62 | + return number |
| 63 | + |
| 64 | + |
| 65 | +if __name__ == "__main__": |
| 66 | + import doctest |
| 67 | + |
| 68 | + doctest.testmod() |
0 commit comments