Skip to content

Commit 933aa6e

Browse files
committed
feat(bit_manipulation): add swap_bits function with doctests and validation
1 parent 788d95b commit 933aa6e

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""
2+
Swaps two bits at given positions in an integer using bitwise operators.
3+
Wikipedia explanation: https://en.wikipedia.org/wiki/Bit_manipulation
4+
"""
5+
6+
7+
def swap_bits(number: int, i: int, j: int) -> int:
8+
"""
9+
Swaps the bits at positions i and j (0-indexed from the right).
10+
11+
>>> swap_bits(28, 0, 2) # 11100 → swap rightmost bits 0 and 2
12+
25
13+
>>> swap_bits(15, 1, 2) # 1111 → swap bits 1 and 2
14+
15
15+
>>> swap_bits(10, 0, 3) # 1010 → swap bits 0 and 3
16+
3
17+
>>> swap_bits(10.5, 0, 3)
18+
Traceback (most recent call last):
19+
...
20+
TypeError: All arguments MUST be integers!
21+
>>> swap_bits(-5, 1, 3)
22+
Traceback (most recent call last):
23+
...
24+
ValueError: The number MUST be non-negative!
25+
>>> swap_bits(10, -1, 2)
26+
Traceback (most recent call last):
27+
...
28+
ValueError: Bit positions MUST be non-negative!
29+
"""
30+
31+
if not all(isinstance(x, int) for x in (number, i, j)):
32+
raise TypeError("All arguments MUST be integers!")
33+
34+
if number < 0:
35+
raise ValueError("The number MUST be non-negative!")
36+
37+
if i < 0 or j < 0:
38+
raise ValueError("Bit positions MUST be non-negative!")
39+
40+
# Extract the bits at positions i and j
41+
bit_i = (number >> i) & 1
42+
bit_j = (number >> j) & 1
43+
44+
# Only swap if the bits are different
45+
if bit_i != bit_j:
46+
# XOR with a mask that has 1s at i and j
47+
number ^= (1 << i) | (1 << j)
48+
49+
return number
50+
51+
52+
if _name_ == "_main_":
53+
import doctest
54+
55+
doctest.testmod()

0 commit comments

Comments
 (0)