From 7cf4aabc805f19aa8aace2bbd61f89f825b7b8b2 Mon Sep 17 00:00:00 2001 From: Basuki Nath Date: Sat, 4 Oct 2025 02:32:55 +0530 Subject: [PATCH 1/3] bit_manipulation: add parity, next_power_of_two, rotate_bits (Author: Basuki Nath) and extend doctests --- bit_manipulation/count_number_of_one_bits.py | 4 ++ bit_manipulation/is_power_of_two.py | 4 ++ bit_manipulation/next_power_of_two.py | 54 +++++++++++++++ bit_manipulation/parity.py | 42 ++++++++++++ bit_manipulation/rotate_bits.py | 69 ++++++++++++++++++++ 5 files changed, 173 insertions(+) create mode 100644 bit_manipulation/next_power_of_two.py create mode 100644 bit_manipulation/parity.py create mode 100644 bit_manipulation/rotate_bits.py diff --git a/bit_manipulation/count_number_of_one_bits.py b/bit_manipulation/count_number_of_one_bits.py index f0c9f927620a..b34ff7e1c5d2 100644 --- a/bit_manipulation/count_number_of_one_bits.py +++ b/bit_manipulation/count_number_of_one_bits.py @@ -20,6 +20,8 @@ def get_set_bits_count_using_brian_kernighans_algorithm(number: int) -> int: Traceback (most recent call last): ... ValueError: the value of input must not be negative + >>> get_set_bits_count_using_brian_kernighans_algorithm(1023) + 10 """ if number < 0: 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: Traceback (most recent call last): ... ValueError: the value of input must not be negative + >>> get_set_bits_count_using_modulo_operator(1024) + 1 """ if number < 0: raise ValueError("the value of input must not be negative") diff --git a/bit_manipulation/is_power_of_two.py b/bit_manipulation/is_power_of_two.py index 023e979fe51c..3dd8df3540bc 100644 --- a/bit_manipulation/is_power_of_two.py +++ b/bit_manipulation/is_power_of_two.py @@ -33,6 +33,10 @@ def is_power_of_two(number: int) -> bool: True >>> is_power_of_two(17) False + >>> is_power_of_two(1024) + True + >>> is_power_of_two(1023) + False >>> is_power_of_two(-1) Traceback (most recent call last): ... diff --git a/bit_manipulation/next_power_of_two.py b/bit_manipulation/next_power_of_two.py new file mode 100644 index 000000000000..59402ab5f513 --- /dev/null +++ b/bit_manipulation/next_power_of_two.py @@ -0,0 +1,54 @@ +""" +Author : Basuki Nath +Date : 2025-10-04 + +Utility to compute the next power of two greater than or equal to n. +""" + +def next_power_of_two(n: int) -> int: + """ + Return the smallest power of two >= n for positive integers. + + >>> next_power_of_two(1) + 1 + >>> next_power_of_two(2) + 2 + >>> next_power_of_two(3) + 4 + >>> next_power_of_two(5) + 8 + >>> next_power_of_two(1025) + 2048 + >>> next_power_of_two(0) + Traceback (most recent call last): + ... + ValueError: n must be positive + >>> next_power_of_two(-3) + Traceback (most recent call last): + ... + ValueError: n must be positive + """ + if n <= 0: + raise ValueError("n must be positive") + # If already a power of two, return it + if n & (n - 1) == 0: + return n + # Otherwise, fill bits to the right + v = n - 1 + v |= v >> 1 + v |= v >> 2 + v |= v >> 4 + v |= v >> 8 + v |= v >> 16 + # for very large ints, continue shifting using Python's arbitrary precision + shift = 32 + while (1 << shift) <= v: + v |= v >> shift + shift <<= 1 + return v + 1 + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/bit_manipulation/parity.py b/bit_manipulation/parity.py new file mode 100644 index 000000000000..ad9e6d00abff --- /dev/null +++ b/bit_manipulation/parity.py @@ -0,0 +1,42 @@ +""" +Author : Basuki Nath +Date : 2025-10-04 + +Simple parity utility for integers. + +The parity is 1 when the number of set bits is odd, otherwise 0. +""" + +def parity(number: int) -> int: + """ + Return 1 if `number` has an odd number of set bits, otherwise 0. + + >>> parity(0) + 0 + >>> parity(1) + 1 + >>> parity(2) # 10b -> one set bit + 1 + >>> parity(3) # 11b -> two set bits + 0 + >>> parity(1023) # 10 ones -> even + 0 + >>> parity(-1) + Traceback (most recent call last): + ... + ValueError: number must not be negative + """ + if number < 0: + raise ValueError("number must not be negative") + # Kernighan's algorithm toggling parity + p = 0 + while number: + p ^= 1 + number &= number - 1 + return p + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/bit_manipulation/rotate_bits.py b/bit_manipulation/rotate_bits.py new file mode 100644 index 000000000000..e2a635ce0b77 --- /dev/null +++ b/bit_manipulation/rotate_bits.py @@ -0,0 +1,69 @@ +""" +Author : Basuki Nath +Date : 2025-10-04 + +Bit rotation helpers for 32-bit unsigned integers. +""" + +def rotate_left32(x: int, k: int) -> int: + """ + Rotate the lower 32 bits of x left by k and return result in 0..2**32-1. + + >>> rotate_left32(1, 1) + 2 + >>> rotate_left32(1, 31) + 2147483648 + >>> rotate_left32(0x80000000, 1) + 1 + >>> rotate_left32(0x12345678, 4) + 591751041 + >>> rotate_left32(-1, 3) + Traceback (most recent call last): + ... + ValueError: x must be a non-negative integer + >>> rotate_left32(1, -1) + Traceback (most recent call last): + ... + ValueError: k must be non-negative + """ + if not isinstance(x, int) or x < 0: + raise ValueError("x must be a non-negative integer") + if not isinstance(k, int) or k < 0: + raise ValueError("k must be non-negative") + mask = (1 << 32) - 1 + k &= 31 + return ((x << k) & mask) | ((x & mask) >> (32 - k)) + + +def rotate_right32(x: int, k: int) -> int: + """ + Rotate the lower 32 bits of x right by k and return result in 0..2**32-1. + + >>> rotate_right32(2, 1) + 1 + >>> rotate_right32(1, 1) + 2147483648 + >>> rotate_right32(0x12345678, 4) + 2166572391 + >>> rotate_right32(-1, 1) + Traceback (most recent call last): + ... + ValueError: x must be a non-negative integer + >>> rotate_right32(1, -3) + Traceback (most recent call last): + ... + ValueError: k must be non-negative + """ + if not isinstance(x, int) or x < 0: + raise ValueError("x must be a non-negative integer") + if not isinstance(k, int) or k < 0: + raise ValueError("k must be non-negative") + mask = (1 << 32) - 1 + k &= 31 + return ((x & mask) >> k) | ((x << (32 - k)) & mask) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From a6f0dd8696c7a94b6bde56780581c791c1de0e4f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 21:10:47 +0000 Subject: [PATCH 2/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- bit_manipulation/next_power_of_two.py | 1 + bit_manipulation/parity.py | 1 + bit_manipulation/rotate_bits.py | 1 + 3 files changed, 3 insertions(+) diff --git a/bit_manipulation/next_power_of_two.py b/bit_manipulation/next_power_of_two.py index 59402ab5f513..4b523c17b130 100644 --- a/bit_manipulation/next_power_of_two.py +++ b/bit_manipulation/next_power_of_two.py @@ -5,6 +5,7 @@ Utility to compute the next power of two greater than or equal to n. """ + def next_power_of_two(n: int) -> int: """ Return the smallest power of two >= n for positive integers. diff --git a/bit_manipulation/parity.py b/bit_manipulation/parity.py index ad9e6d00abff..019c88deea30 100644 --- a/bit_manipulation/parity.py +++ b/bit_manipulation/parity.py @@ -7,6 +7,7 @@ The parity is 1 when the number of set bits is odd, otherwise 0. """ + def parity(number: int) -> int: """ Return 1 if `number` has an odd number of set bits, otherwise 0. diff --git a/bit_manipulation/rotate_bits.py b/bit_manipulation/rotate_bits.py index e2a635ce0b77..521ab8de203f 100644 --- a/bit_manipulation/rotate_bits.py +++ b/bit_manipulation/rotate_bits.py @@ -5,6 +5,7 @@ Bit rotation helpers for 32-bit unsigned integers. """ + def rotate_left32(x: int, k: int) -> int: """ Rotate the lower 32 bits of x left by k and return result in 0..2**32-1. From 6882029e7cb6c5ec3b7ff0416f8cf35ff7a6ac57 Mon Sep 17 00:00:00 2001 From: cclauss Date: Sun, 13 Sep 2026 14:38:46 +0000 Subject: [PATCH 3/3] updating DIRECTORY.md --- DIRECTORY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index a092d2dd8fe8..ea5231873a53 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -97,9 +97,12 @@ * [Is Power Of Two](bit_manipulation/is_power_of_two.py) * [Largest Pow Of Two Le Num](bit_manipulation/largest_pow_of_two_le_num.py) * [Missing Number](bit_manipulation/missing_number.py) + * [Next Power Of Two](bit_manipulation/next_power_of_two.py) * [Numbers Different Signs](bit_manipulation/numbers_different_signs.py) + * [Parity](bit_manipulation/parity.py) * [Power Of 4](bit_manipulation/power_of_4.py) * [Reverse Bits](bit_manipulation/reverse_bits.py) + * [Rotate Bits](bit_manipulation/rotate_bits.py) * [Single Bit Manipulation Operations](bit_manipulation/single_bit_manipulation_operations.py) * [Swap All Odd And Even Bits](bit_manipulation/swap_all_odd_and_even_bits.py)