diff --git a/DIRECTORY.md b/DIRECTORY.md index 934db9477b6..1c08021c544 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -26,6 +26,7 @@ * [Reverse Bits](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/reverse_bits.rs) * [Sum of Two Integers](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/sum_of_two_integers.rs) * [Swap Odd and Even Bits](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/swap_odd_even_bits.rs) + * [Trailing Zeros](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/binary_count_trailing_zeros.rs) * [Two's Complement](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/twos_complement.rs) * Ciphers * [AES](https://github.com/TheAlgorithms/Rust/blob/master/src/ciphers/aes.rs) diff --git a/src/bit_manipulation/binary_count_trailing_zeros.rs b/src/bit_manipulation/binary_count_trailing_zeros.rs new file mode 100644 index 00000000000..9950375ddf9 --- /dev/null +++ b/src/bit_manipulation/binary_count_trailing_zeros.rs @@ -0,0 +1,119 @@ +/// Counts the number of trailing zeros in the binary representation of a number +/// +/// # Arguments +/// +/// * `num` - The input number +/// +/// # Returns +/// +/// The number of trailing zeros in the binary representation +/// +/// # Examples +/// +/// ``` +/// use the_algorithms_rust::bit_manipulation::binary_count_trailing_zeros; +/// +/// assert_eq!(binary_count_trailing_zeros(25), 0); +/// assert_eq!(binary_count_trailing_zeros(36), 2); +/// assert_eq!(binary_count_trailing_zeros(16), 4); +/// assert_eq!(binary_count_trailing_zeros(58), 1); +/// ``` +pub fn binary_count_trailing_zeros(num: u64) -> u32 { + if num == 0 { + return 0; + } + num.trailing_zeros() +} + +/// Alternative implementation using bit manipulation +/// +/// Uses the bit manipulation trick: log2(num & -num) +/// +/// # Examples +/// +/// ``` +/// // This function uses bit manipulation: log2(num & -num) +/// // where num & -num isolates the rightmost set bit +/// # fn binary_count_trailing_zeros_bitwise(num: u64) -> u32 { +/// # if num == 0 { return 0; } +/// # let rightmost_set_bit = num & (num.wrapping_neg()); +/// # 63 - rightmost_set_bit.leading_zeros() +/// # } +/// assert_eq!(binary_count_trailing_zeros_bitwise(25), 0); +/// assert_eq!(binary_count_trailing_zeros_bitwise(36), 2); +/// assert_eq!(binary_count_trailing_zeros_bitwise(16), 4); +/// ``` +#[allow(dead_code)] +pub fn binary_count_trailing_zeros_bitwise(num: u64) -> u32 { + if num == 0 { + return 0; + } + + let rightmost_set_bit = num & (num.wrapping_neg()); + 63 - rightmost_set_bit.leading_zeros() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_basic_cases() { + assert_eq!(binary_count_trailing_zeros(25), 0); + assert_eq!(binary_count_trailing_zeros(36), 2); + assert_eq!(binary_count_trailing_zeros(16), 4); + assert_eq!(binary_count_trailing_zeros(58), 1); + assert_eq!(binary_count_trailing_zeros(4294967296), 32); + } + + #[test] + fn test_zero() { + assert_eq!(binary_count_trailing_zeros(0), 0); + } + + #[test] + fn test_powers_of_two() { + assert_eq!(binary_count_trailing_zeros(1), 0); + assert_eq!(binary_count_trailing_zeros(2), 1); + assert_eq!(binary_count_trailing_zeros(4), 2); + assert_eq!(binary_count_trailing_zeros(8), 3); + assert_eq!(binary_count_trailing_zeros(1024), 10); + } + + #[test] + fn test_bitwise_vs_builtin() { + // Test that bitwise implementation matches built-in trailing_zeros() + let test_cases = vec![ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 16, + 25, + 36, + 58, + 64, + 100, + 128, + 256, + 512, + 1024, + 4294967296, + u64::MAX - 1, + u64::MAX, + ]; + + for num in test_cases { + assert_eq!( + binary_count_trailing_zeros(num), + binary_count_trailing_zeros_bitwise(num), + "Mismatch for input: {num}" + ); + } + } +} diff --git a/src/bit_manipulation/mod.rs b/src/bit_manipulation/mod.rs index 95bbb755123..606dc81e89e 100644 --- a/src/bit_manipulation/mod.rs +++ b/src/bit_manipulation/mod.rs @@ -1,4 +1,5 @@ mod binary_coded_decimal; +mod binary_count_trailing_zeros; mod counting_bits; mod find_previous_power_of_two; mod highest_set_bit; @@ -10,6 +11,7 @@ mod swap_odd_even_bits; mod twos_complement; pub use self::binary_coded_decimal::binary_coded_decimal; +pub use self::binary_count_trailing_zeros::binary_count_trailing_zeros; pub use self::counting_bits::count_set_bits; pub use self::find_previous_power_of_two::find_previous_power_of_two; pub use self::highest_set_bit::find_highest_set_bit;