diff --git a/src/bit_manipulation/mod.rs b/src/bit_manipulation/mod.rs index 1c9fae8d3af..027c4b81817 100644 --- a/src/bit_manipulation/mod.rs +++ b/src/bit_manipulation/mod.rs @@ -1,7 +1,9 @@ mod counting_bits; mod highest_set_bit; +mod n_bits_gray_code; mod sum_of_two_integers; pub use counting_bits::count_set_bits; pub use highest_set_bit::find_highest_set_bit; +pub use n_bits_gray_code::generate_gray_code; pub use sum_of_two_integers::add_two_integers; diff --git a/src/bit_manipulation/n_bits_gray_code.rs b/src/bit_manipulation/n_bits_gray_code.rs new file mode 100644 index 00000000000..64c717bc761 --- /dev/null +++ b/src/bit_manipulation/n_bits_gray_code.rs @@ -0,0 +1,75 @@ +/// Custom error type for Gray code generation. +#[derive(Debug, PartialEq)] +pub enum GrayCodeError { + ZeroBitCount, +} + +/// Generates an n-bit Gray code sequence using the direct Gray code formula. +/// +/// # Arguments +/// +/// * `n` - The number of bits for the Gray code. +/// +/// # Returns +/// +/// A vector of Gray code sequences as strings. +pub fn generate_gray_code(n: usize) -> Result, GrayCodeError> { + if n == 0 { + return Err(GrayCodeError::ZeroBitCount); + } + + let num_codes = 1 << n; + let mut result = Vec::with_capacity(num_codes); + + for i in 0..num_codes { + let gray = i ^ (i >> 1); + let gray_code = (0..n) + .rev() + .map(|bit| if gray & (1 << bit) != 0 { '1' } else { '0' }) + .collect::(); + result.push(gray_code); + } + + Ok(result) +} + +#[cfg(test)] +mod tests { + use super::*; + + macro_rules! gray_code_tests { + ($($name:ident: $test_case:expr,)*) => { + $( + #[test] + fn $name() { + let (input, expected) = $test_case; + assert_eq!(generate_gray_code(input), expected); + } + )* + }; + } + + gray_code_tests! { + zero_bit_count: (0, Err(GrayCodeError::ZeroBitCount)), + gray_code_1_bit: (1, Ok(vec![ + "0".to_string(), + "1".to_string(), + ])), + gray_code_2_bit: (2, Ok(vec![ + "00".to_string(), + "01".to_string(), + "11".to_string(), + "10".to_string(), + ])), + gray_code_3_bit: (3, Ok(vec![ + "000".to_string(), + "001".to_string(), + "011".to_string(), + "010".to_string(), + "110".to_string(), + "111".to_string(), + "101".to_string(), + "100".to_string(), + ])), + } +}