From 98ee074a01b33bed0a2517f495ec14d6c0683abe Mon Sep 17 00:00:00 2001 From: Arun Kishore Voleti <49097688+ArunKishoreVoleti@users.noreply.github.com> Date: Tue, 14 Oct 2025 14:31:50 +0530 Subject: [PATCH 1/6] Add set bits count using lookup table method Introduced get_set_bits_count_using_lookup_table to efficiently count set bits in a 32-bit integer using a precomputed lookup table. Updated benchmark to compare the new method alongside existing algorithms. --- bit_manipulation/count_number_of_one_bits.py | 49 +++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/bit_manipulation/count_number_of_one_bits.py b/bit_manipulation/count_number_of_one_bits.py index f0c9f927620a..418777760ace 100644 --- a/bit_manipulation/count_number_of_one_bits.py +++ b/bit_manipulation/count_number_of_one_bits.py @@ -60,20 +60,58 @@ def get_set_bits_count_using_modulo_operator(number: int) -> int: return result +def get_set_bits_count_using_lookup_table(number: int) -> int: + """ + Count the number of set bits in a 32-bit integer using a precomputed lookup table. + >>> get_set_bits_count_using_lookup_table(25) + 3 + >>> get_set_bits_count_using_lookup_table(37) + 3 + >>> get_set_bits_count_using_lookup_table(21) + 3 + >>> get_set_bits_count_using_lookup_table(58) + 4 + >>> get_set_bits_count_using_lookup_table(0) + 0 + >>> get_set_bits_count_using_lookup_table(256) + 1 + >>> get_set_bits_count_using_lookup_table(-1) + Traceback (most recent call last): + ... + ValueError: the value of input must not be negative + """ + _LOOKUP_TABLE = [bin(i).count("1") for i in range(256)] + + if number < 0: + raise ValueError("the value of input must not be negative") + + # Split 32-bit number into four 8-bit chunks and use lookup table + return ( + _LOOKUP_TABLE[number & 0xFF] + + _LOOKUP_TABLE[(number >> 8) & 0xFF] + + _LOOKUP_TABLE[(number >> 16) & 0xFF] + + _LOOKUP_TABLE[(number >> 24) & 0xFF] + ) + + + def benchmark() -> None: """ - Benchmark code for comparing 2 functions, with different length int values. - Brian Kernighan's algorithm is consistently faster than using modulo_operator. + Benchmark code for comparing 3 functions, with different length int values. + Brian Kernighan's algorithm is consistently faster than using modulo_operator, + and the lookup table method is often the fastest for repeated calls. """ def do_benchmark(number: int) -> None: setup = "import __main__ as z" print(f"Benchmark when {number = }:") + print(f"{get_set_bits_count_using_modulo_operator(number) = }") timing = timeit( f"z.get_set_bits_count_using_modulo_operator({number})", setup=setup ) print(f"timeit() runs in {timing} seconds") + print(f"{get_set_bits_count_using_brian_kernighans_algorithm(number) = }") timing = timeit( f"z.get_set_bits_count_using_brian_kernighans_algorithm({number})", @@ -81,6 +119,13 @@ def do_benchmark(number: int) -> None: ) print(f"timeit() runs in {timing} seconds") + print(f"{get_set_bits_count_using_lookup_table(number) = }") + timing = timeit( + f"z.get_set_bits_count_using_lookup_table({number})", + setup=setup, + ) + print(f"timeit() runs in {timing} seconds") + for number in (25, 37, 58, 0): do_benchmark(number) print() From a551700fed775a1839666bdd1efae770d8e58933 Mon Sep 17 00:00:00 2001 From: Arun Kishore Voleti <49097688+ArunKishoreVoleti@users.noreply.github.com> Date: Tue, 14 Oct 2025 14:40:03 +0530 Subject: [PATCH 2/6] Update count_number_of_one_bits.py --- bit_manipulation/count_number_of_one_bits.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bit_manipulation/count_number_of_one_bits.py b/bit_manipulation/count_number_of_one_bits.py index 418777760ace..d6cfd970ec93 100644 --- a/bit_manipulation/count_number_of_one_bits.py +++ b/bit_manipulation/count_number_of_one_bits.py @@ -63,6 +63,10 @@ def get_set_bits_count_using_modulo_operator(number: int) -> int: def get_set_bits_count_using_lookup_table(number: int) -> int: """ Count the number of set bits in a 32-bit integer using a precomputed lookup table. + + Note: I see similar approach in GeeksforGeeks, but their implementation is little different. + Link to Code: https://www.geeksforgeeks.org/dsa/count-set-bits-integer-using-lookup-table/ + >>> get_set_bits_count_using_lookup_table(25) 3 >>> get_set_bits_count_using_lookup_table(37) From f4d7f0d03b85424fe76413459d8e6979e4d02fed Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 09:11:47 +0000 Subject: [PATCH 3/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- bit_manipulation/count_number_of_one_bits.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bit_manipulation/count_number_of_one_bits.py b/bit_manipulation/count_number_of_one_bits.py index d6cfd970ec93..c390d8abf2f2 100644 --- a/bit_manipulation/count_number_of_one_bits.py +++ b/bit_manipulation/count_number_of_one_bits.py @@ -66,7 +66,7 @@ def get_set_bits_count_using_lookup_table(number: int) -> int: Note: I see similar approach in GeeksforGeeks, but their implementation is little different. Link to Code: https://www.geeksforgeeks.org/dsa/count-set-bits-integer-using-lookup-table/ - + >>> get_set_bits_count_using_lookup_table(25) 3 >>> get_set_bits_count_using_lookup_table(37) @@ -98,7 +98,6 @@ def get_set_bits_count_using_lookup_table(number: int) -> int: ) - def benchmark() -> None: """ Benchmark code for comparing 3 functions, with different length int values. From 832f9b0d6a1de268c3cc03ba79173ef07bb488e1 Mon Sep 17 00:00:00 2001 From: Arun Kishore Voleti <49097688+ArunKishoreVoleti@users.noreply.github.com> Date: Tue, 14 Oct 2025 14:44:30 +0530 Subject: [PATCH 4/6] Update count_number_of_one_bits.py --- bit_manipulation/count_number_of_one_bits.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/bit_manipulation/count_number_of_one_bits.py b/bit_manipulation/count_number_of_one_bits.py index d6cfd970ec93..adc7d7f035ec 100644 --- a/bit_manipulation/count_number_of_one_bits.py +++ b/bit_manipulation/count_number_of_one_bits.py @@ -64,9 +64,10 @@ def get_set_bits_count_using_lookup_table(number: int) -> int: """ Count the number of set bits in a 32-bit integer using a precomputed lookup table. - Note: I see similar approach in GeeksforGeeks, but their implementation is little different. - Link to Code: https://www.geeksforgeeks.org/dsa/count-set-bits-integer-using-lookup-table/ - + Note: I see similar approach in GeeksforGeeks, but the implementation is little different. + Link to Code: + https://www.geeksforgeeks.org/dsa/count-set-bits-integer-using-lookup-table/ + >>> get_set_bits_count_using_lookup_table(25) 3 >>> get_set_bits_count_using_lookup_table(37) @@ -84,17 +85,17 @@ def get_set_bits_count_using_lookup_table(number: int) -> int: ... ValueError: the value of input must not be negative """ - _LOOKUP_TABLE = [bin(i).count("1") for i in range(256)] + _lookup_table = [bin(i).count("1") for i in range(256)] if number < 0: raise ValueError("the value of input must not be negative") # Split 32-bit number into four 8-bit chunks and use lookup table return ( - _LOOKUP_TABLE[number & 0xFF] - + _LOOKUP_TABLE[(number >> 8) & 0xFF] - + _LOOKUP_TABLE[(number >> 16) & 0xFF] - + _LOOKUP_TABLE[(number >> 24) & 0xFF] + _lookup_table[number & 0xFF] + + _lookup_table[(number >> 8) & 0xFF] + + _lookup_table[(number >> 16) & 0xFF] + + _lookup_table[(number >> 24) & 0xFF] ) From 2308e2ab44269aae0336f3287eb97540a75bd886 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 09:16:38 +0000 Subject: [PATCH 5/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- bit_manipulation/count_number_of_one_bits.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bit_manipulation/count_number_of_one_bits.py b/bit_manipulation/count_number_of_one_bits.py index adc7d7f035ec..04d5abaf3ca7 100644 --- a/bit_manipulation/count_number_of_one_bits.py +++ b/bit_manipulation/count_number_of_one_bits.py @@ -99,7 +99,6 @@ def get_set_bits_count_using_lookup_table(number: int) -> int: ) - def benchmark() -> None: """ Benchmark code for comparing 3 functions, with different length int values. From 1e6ba2b77e1aabfbace77327c0e1dd3a16c5787e Mon Sep 17 00:00:00 2001 From: Arun Kishore Voleti <49097688+ArunKishoreVoleti@users.noreply.github.com> Date: Tue, 14 Oct 2025 14:48:04 +0530 Subject: [PATCH 6/6] Update count_number_of_one_bits.py Reduced line size --- bit_manipulation/count_number_of_one_bits.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bit_manipulation/count_number_of_one_bits.py b/bit_manipulation/count_number_of_one_bits.py index adc7d7f035ec..e9395685bdda 100644 --- a/bit_manipulation/count_number_of_one_bits.py +++ b/bit_manipulation/count_number_of_one_bits.py @@ -64,7 +64,7 @@ def get_set_bits_count_using_lookup_table(number: int) -> int: """ Count the number of set bits in a 32-bit integer using a precomputed lookup table. - Note: I see similar approach in GeeksforGeeks, but the implementation is little different. + I see similar approach in GeeksforGeeks, but the implementation is different. Link to Code: https://www.geeksforgeeks.org/dsa/count-set-bits-integer-using-lookup-table/