From e3d9a63f07108569b7a341fb1fabefb52f14a9a3 Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Wed, 11 Sep 2024 19:28:16 +0700 Subject: [PATCH 1/2] chore[clean_up]: improve bit manipulation algorithm implementations - Add docstring to file and function - Rewrite tests using macro --- src/bit_manipulation/counting_bits.rs | 58 ++++++++++-------- src/bit_manipulation/highest_set_bit.rs | 53 +++++++++-------- src/bit_manipulation/sum_of_two_integers.rs | 66 +++++++++++---------- 3 files changed, 96 insertions(+), 81 deletions(-) diff --git a/src/bit_manipulation/counting_bits.rs b/src/bit_manipulation/counting_bits.rs index eabd529d140..9357ca3080c 100644 --- a/src/bit_manipulation/counting_bits.rs +++ b/src/bit_manipulation/counting_bits.rs @@ -1,11 +1,19 @@ -/* -The counting bits algorithm, also known as the "population count" or "Hamming weight," -calculates the number of set bits (1s) in the binary representation of an unsigned integer. -It uses a technique known as Brian Kernighan's algorithm, which efficiently clears the least -significant set bit in each iteration. -*/ - -pub fn count_set_bits(mut n: u32) -> u32 { +//! This module implements a function to count the number of set bits (1s) +//! in the binary representation of an unsigned integer. +//! It uses Brian Kernighan's algorithm, which efficiently clears the least significant +//! set bit in each iteration until all bits are cleared. +//! The algorithm runs in O(k), where k is the number of set bits. + +/// Counts the number of set bits in an unsigned integer. +/// +/// # Arguments +/// +/// * `n` - An unsigned 32-bit integer whose set bits will be counted. +/// +/// # Returns +/// +/// * `usize` - The number of set bits (1s) in the binary representation of the input number. +pub fn count_set_bits(mut n: usize) -> usize { // Initialize a variable to keep track of the count of set bits let mut count = 0; while n > 0 { @@ -24,23 +32,23 @@ pub fn count_set_bits(mut n: u32) -> u32 { mod tests { use super::*; - #[test] - fn test_count_set_bits_zero() { - assert_eq!(count_set_bits(0), 0); - } - - #[test] - fn test_count_set_bits_one() { - assert_eq!(count_set_bits(1), 1); + macro_rules! test_count_set_bits { + ($($name:ident: $test_case:expr,)*) => { + $( + #[test] + fn $name() { + let (input, expected) = $test_case; + assert_eq!(count_set_bits(input), expected); + } + )* + }; } - - #[test] - fn test_count_set_bits_power_of_two() { - assert_eq!(count_set_bits(16), 1); // 16 is 2^4, only one set bit - } - - #[test] - fn test_count_set_bits_all_set_bits() { - assert_eq!(count_set_bits(u32::MAX), 32); // Maximum value for u32, all set bits + test_count_set_bits! { + test_count_set_bits_zero: (0, 0), + test_count_set_bits_one: (1, 1), + test_count_set_bits_power_of_two: (16, 1), + test_count_set_bits_all_set_bits: (usize::MAX, std::mem::size_of::() * 8), + test_count_set_bits_alternating_bits: (0b10101010, 4), + test_count_set_bits_mixed_bits: (0b11011011, 6), } } diff --git a/src/bit_manipulation/highest_set_bit.rs b/src/bit_manipulation/highest_set_bit.rs index 4952c56be09..80405c0a2d3 100644 --- a/src/bit_manipulation/highest_set_bit.rs +++ b/src/bit_manipulation/highest_set_bit.rs @@ -1,15 +1,18 @@ -// Find Highest Set Bit in Rust -// This code provides a function to calculate the position (or index) of the most significant bit set to 1 in a given integer. - -// Define a function to find the highest set bit. -pub fn find_highest_set_bit(num: i32) -> Option { - if num < 0 { - // Input cannot be negative. - panic!("Input cannot be negative"); - } - +//! This module provides a function to find the position of the most significant bit (MSB) +//! set to 1 in a given positive integer. + +/// Finds the position of the highest (most significant) set bit in a positive integer. +/// +/// # Arguments +/// +/// * `num` - An integer value for which the highest set bit will be determined. +/// +/// # Returns +/// +/// * Returns `Some(position)` if a set bit exists or `None` if no bit is set. +pub fn find_highest_set_bit(num: usize) -> Option { if num == 0 { - return None; // No bit is set, return None. + return None; } let mut position = 0; @@ -27,22 +30,20 @@ pub fn find_highest_set_bit(num: i32) -> Option { mod tests { use super::*; - #[test] - fn test_positive_number() { - let num = 18; - assert_eq!(find_highest_set_bit(num), Some(4)); - } - - #[test] - fn test_zero() { - let num = 0; - assert_eq!(find_highest_set_bit(num), None); + macro_rules! test_find_highest_set_bit { + ($($name:ident: $test_case:expr,)*) => { + $( + #[test] + fn $name() { + let (input, expected) = $test_case; + assert_eq!(find_highest_set_bit(input), expected); + } + )* + }; } - #[test] - #[should_panic(expected = "Input cannot be negative")] - fn test_negative_number() { - let num = -12; - find_highest_set_bit(num); + test_find_highest_set_bit! { + test_positive_number: (18, Some(4)), + test_zero: (0, None), } } diff --git a/src/bit_manipulation/sum_of_two_integers.rs b/src/bit_manipulation/sum_of_two_integers.rs index 079ac4c3177..1ce91693965 100644 --- a/src/bit_manipulation/sum_of_two_integers.rs +++ b/src/bit_manipulation/sum_of_two_integers.rs @@ -1,19 +1,22 @@ -/** - * This algorithm demonstrates how to add two integers without using the + operator - * but instead relying on bitwise operations, like bitwise XOR and AND, to simulate - * the addition. It leverages bit manipulation to compute the sum efficiently. - */ +//! This module provides a function to add two integers without using the `+` operator. +//! It relies on bitwise operations (XOR and AND) to compute the sum, simulating the addition process. -pub fn add_two_integers(a: i32, b: i32) -> i32 { - let mut a = a; - let mut b = b; +/// Adds two integers using bitwise operations. +/// +/// # Arguments +/// +/// * `a` - The first integer to be added. +/// * `b` - The second integer to be added. +/// +/// # Returns +/// +/// * `isize` - The result of adding the two integers. +pub fn add_two_integers(mut a: isize, mut b: isize) -> isize { let mut carry; - let mut sum; - // Iterate until there is no carry left while b != 0 { - sum = a ^ b; // XOR operation to find the sum without carry - carry = (a & b) << 1; // AND operation to find the carry, shifted left by 1 + let sum = a ^ b; + carry = (a & b) << 1; a = sum; b = carry; } @@ -23,26 +26,29 @@ pub fn add_two_integers(a: i32, b: i32) -> i32 { #[cfg(test)] mod tests { - use super::add_two_integers; + use super::*; - #[test] - fn test_add_two_integers_positive() { - assert_eq!(add_two_integers(3, 5), 8); - assert_eq!(add_two_integers(100, 200), 300); - assert_eq!(add_two_integers(65535, 1), 65536); + macro_rules! test_add_two_integers { + ($($name:ident: $test_case:expr,)*) => { + $( + #[test] + fn $name() { + let (a, b, expected) = $test_case; + assert_eq!(add_two_integers(a, b), expected); + } + )* + }; } - #[test] - fn test_add_two_integers_negative() { - assert_eq!(add_two_integers(-10, 6), -4); - assert_eq!(add_two_integers(-50, -30), -80); - assert_eq!(add_two_integers(-1, -1), -2); - } - - #[test] - fn test_add_two_integers_zero() { - assert_eq!(add_two_integers(0, 0), 0); - assert_eq!(add_two_integers(0, 42), 42); - assert_eq!(add_two_integers(0, -42), -42); + test_add_two_integers! { + test_add_two_integers_positive: (3, 5, 8), + test_add_two_integers_large_positive: (100, 200, 300), + test_add_two_integers_edge_positive: (65535, 1, 65536), + test_add_two_integers_negative: (-10, 6, -4), + test_add_two_integers_both_negative: (-50, -30, -80), + test_add_two_integers_edge_negative: (-1, -1, -2), + test_add_two_integers_zero: (0, 0, 0), + test_add_two_integers_zero_with_positive: (0, 42, 42), + test_add_two_integers_zero_with_negative: (0, -42, -42), } } From cd17c1b670c1d3aa84a27b656bece0a10ab0272f Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Mon, 16 Sep 2024 08:21:53 +0700 Subject: [PATCH 2/2] chore: update tests --- src/bit_manipulation/highest_set_bit.rs | 5 ++++- src/bit_manipulation/sum_of_two_integers.rs | 23 +++++++++++---------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/bit_manipulation/highest_set_bit.rs b/src/bit_manipulation/highest_set_bit.rs index 80405c0a2d3..3488f49a7d9 100644 --- a/src/bit_manipulation/highest_set_bit.rs +++ b/src/bit_manipulation/highest_set_bit.rs @@ -44,6 +44,9 @@ mod tests { test_find_highest_set_bit! { test_positive_number: (18, Some(4)), - test_zero: (0, None), + test_0: (0, None), + test_1: (1, Some(0)), + test_2: (2, Some(1)), + test_3: (3, Some(1)), } } diff --git a/src/bit_manipulation/sum_of_two_integers.rs b/src/bit_manipulation/sum_of_two_integers.rs index 1ce91693965..45d3532b173 100644 --- a/src/bit_manipulation/sum_of_two_integers.rs +++ b/src/bit_manipulation/sum_of_two_integers.rs @@ -33,22 +33,23 @@ mod tests { $( #[test] fn $name() { - let (a, b, expected) = $test_case; - assert_eq!(add_two_integers(a, b), expected); + let (a, b) = $test_case; + assert_eq!(add_two_integers(a, b), a + b); + assert_eq!(add_two_integers(b, a), a + b); } )* }; } test_add_two_integers! { - test_add_two_integers_positive: (3, 5, 8), - test_add_two_integers_large_positive: (100, 200, 300), - test_add_two_integers_edge_positive: (65535, 1, 65536), - test_add_two_integers_negative: (-10, 6, -4), - test_add_two_integers_both_negative: (-50, -30, -80), - test_add_two_integers_edge_negative: (-1, -1, -2), - test_add_two_integers_zero: (0, 0, 0), - test_add_two_integers_zero_with_positive: (0, 42, 42), - test_add_two_integers_zero_with_negative: (0, -42, -42), + test_add_two_integers_positive: (3, 5), + test_add_two_integers_large_positive: (100, 200), + test_add_two_integers_edge_positive: (65535, 1), + test_add_two_integers_negative: (-10, 6), + test_add_two_integers_both_negative: (-50, -30), + test_add_two_integers_edge_negative: (-1, -1), + test_add_two_integers_zero: (0, 0), + test_add_two_integers_zero_with_positive: (0, 42), + test_add_two_integers_zero_with_negative: (0, -42), } }