Skip to content

Commit b447c78

Browse files
basukinathpre-commit-ci[bot]cclauss
authored
add bit_manipulation: add parity, next_power_of_two, rotate_bits codes (#13157)
* bit_manipulation: add parity, next_power_of_two, rotate_bits (Author: Basuki Nath) and extend doctests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * updating DIRECTORY.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss <cclauss@me.com> Co-authored-by: cclauss <cclauss@users.noreply.github.com>
1 parent 2b6f77b commit b447c78

6 files changed

Lines changed: 179 additions & 0 deletions

File tree

DIRECTORY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,12 @@
9797
* [Is Power Of Two](bit_manipulation/is_power_of_two.py)
9898
* [Largest Pow Of Two Le Num](bit_manipulation/largest_pow_of_two_le_num.py)
9999
* [Missing Number](bit_manipulation/missing_number.py)
100+
* [Next Power Of Two](bit_manipulation/next_power_of_two.py)
100101
* [Numbers Different Signs](bit_manipulation/numbers_different_signs.py)
102+
* [Parity](bit_manipulation/parity.py)
101103
* [Power Of 4](bit_manipulation/power_of_4.py)
102104
* [Reverse Bits](bit_manipulation/reverse_bits.py)
105+
* [Rotate Bits](bit_manipulation/rotate_bits.py)
103106
* [Single Bit Manipulation Operations](bit_manipulation/single_bit_manipulation_operations.py)
104107
* [Swap All Odd And Even Bits](bit_manipulation/swap_all_odd_and_even_bits.py)
105108

bit_manipulation/count_number_of_one_bits.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ def get_set_bits_count_using_brian_kernighans_algorithm(number: int) -> int:
2020
Traceback (most recent call last):
2121
...
2222
ValueError: the value of input must not be negative
23+
>>> get_set_bits_count_using_brian_kernighans_algorithm(1023)
24+
10
2325
"""
2426
if number < 0:
2527
raise ValueError("the value of input must not be negative")
@@ -49,6 +51,8 @@ def get_set_bits_count_using_modulo_operator(number: int) -> int:
4951
Traceback (most recent call last):
5052
...
5153
ValueError: the value of input must not be negative
54+
>>> get_set_bits_count_using_modulo_operator(1024)
55+
1
5256
"""
5357
if number < 0:
5458
raise ValueError("the value of input must not be negative")

bit_manipulation/is_power_of_two.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ def is_power_of_two(number: int) -> bool:
3333
True
3434
>>> is_power_of_two(17)
3535
False
36+
>>> is_power_of_two(1024)
37+
True
38+
>>> is_power_of_two(1023)
39+
False
3640
>>> is_power_of_two(-1)
3741
Traceback (most recent call last):
3842
...
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""
2+
Author : Basuki Nath
3+
Date : 2025-10-04
4+
5+
Utility to compute the next power of two greater than or equal to n.
6+
"""
7+
8+
9+
def next_power_of_two(n: int) -> int:
10+
"""
11+
Return the smallest power of two >= n for positive integers.
12+
13+
>>> next_power_of_two(1)
14+
1
15+
>>> next_power_of_two(2)
16+
2
17+
>>> next_power_of_two(3)
18+
4
19+
>>> next_power_of_two(5)
20+
8
21+
>>> next_power_of_two(1025)
22+
2048
23+
>>> next_power_of_two(0)
24+
Traceback (most recent call last):
25+
...
26+
ValueError: n must be positive
27+
>>> next_power_of_two(-3)
28+
Traceback (most recent call last):
29+
...
30+
ValueError: n must be positive
31+
"""
32+
if n <= 0:
33+
raise ValueError("n must be positive")
34+
# If already a power of two, return it
35+
if n & (n - 1) == 0:
36+
return n
37+
# Otherwise, fill bits to the right
38+
v = n - 1
39+
v |= v >> 1
40+
v |= v >> 2
41+
v |= v >> 4
42+
v |= v >> 8
43+
v |= v >> 16
44+
# for very large ints, continue shifting using Python's arbitrary precision
45+
shift = 32
46+
while (1 << shift) <= v:
47+
v |= v >> shift
48+
shift <<= 1
49+
return v + 1
50+
51+
52+
if __name__ == "__main__":
53+
import doctest
54+
55+
doctest.testmod()

bit_manipulation/parity.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""
2+
Author : Basuki Nath
3+
Date : 2025-10-04
4+
5+
Simple parity utility for integers.
6+
7+
The parity is 1 when the number of set bits is odd, otherwise 0.
8+
"""
9+
10+
11+
def parity(number: int) -> int:
12+
"""
13+
Return 1 if `number` has an odd number of set bits, otherwise 0.
14+
15+
>>> parity(0)
16+
0
17+
>>> parity(1)
18+
1
19+
>>> parity(2) # 10b -> one set bit
20+
1
21+
>>> parity(3) # 11b -> two set bits
22+
0
23+
>>> parity(1023) # 10 ones -> even
24+
0
25+
>>> parity(-1)
26+
Traceback (most recent call last):
27+
...
28+
ValueError: number must not be negative
29+
"""
30+
if number < 0:
31+
raise ValueError("number must not be negative")
32+
# Kernighan's algorithm toggling parity
33+
p = 0
34+
while number:
35+
p ^= 1
36+
number &= number - 1
37+
return p
38+
39+
40+
if __name__ == "__main__":
41+
import doctest
42+
43+
doctest.testmod()

bit_manipulation/rotate_bits.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
"""
2+
Author : Basuki Nath
3+
Date : 2025-10-04
4+
5+
Bit rotation helpers for 32-bit unsigned integers.
6+
"""
7+
8+
9+
def rotate_left32(x: int, k: int) -> int:
10+
"""
11+
Rotate the lower 32 bits of x left by k and return result in 0..2**32-1.
12+
13+
>>> rotate_left32(1, 1)
14+
2
15+
>>> rotate_left32(1, 31)
16+
2147483648
17+
>>> rotate_left32(0x80000000, 1)
18+
1
19+
>>> rotate_left32(0x12345678, 4)
20+
591751041
21+
>>> rotate_left32(-1, 3)
22+
Traceback (most recent call last):
23+
...
24+
ValueError: x must be a non-negative integer
25+
>>> rotate_left32(1, -1)
26+
Traceback (most recent call last):
27+
...
28+
ValueError: k must be non-negative
29+
"""
30+
if not isinstance(x, int) or x < 0:
31+
raise ValueError("x must be a non-negative integer")
32+
if not isinstance(k, int) or k < 0:
33+
raise ValueError("k must be non-negative")
34+
mask = (1 << 32) - 1
35+
k &= 31
36+
return ((x << k) & mask) | ((x & mask) >> (32 - k))
37+
38+
39+
def rotate_right32(x: int, k: int) -> int:
40+
"""
41+
Rotate the lower 32 bits of x right by k and return result in 0..2**32-1.
42+
43+
>>> rotate_right32(2, 1)
44+
1
45+
>>> rotate_right32(1, 1)
46+
2147483648
47+
>>> rotate_right32(0x12345678, 4)
48+
2166572391
49+
>>> rotate_right32(-1, 1)
50+
Traceback (most recent call last):
51+
...
52+
ValueError: x must be a non-negative integer
53+
>>> rotate_right32(1, -3)
54+
Traceback (most recent call last):
55+
...
56+
ValueError: k must be non-negative
57+
"""
58+
if not isinstance(x, int) or x < 0:
59+
raise ValueError("x must be a non-negative integer")
60+
if not isinstance(k, int) or k < 0:
61+
raise ValueError("k must be non-negative")
62+
mask = (1 << 32) - 1
63+
k &= 31
64+
return ((x & mask) >> k) | ((x << (32 - k)) & mask)
65+
66+
67+
if __name__ == "__main__":
68+
import doctest
69+
70+
doctest.testmod()

0 commit comments

Comments
 (0)