Skip to content

Commit 35a5743

Browse files
feat: add Hamming distance algorithm (#983)
1 parent ba7ca98 commit 35a5743

3 files changed

Lines changed: 139 additions & 0 deletions

File tree

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* Bit Manipulation
2020
* [Binary Coded Decimal](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/binary_coded_decimal.rs)
2121
* [Counting Bits](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/counting_bits.rs)
22+
* [Hamming Distance](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/hamming_distance.rs)
2223
* [Highest Set Bit](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/highest_set_bit.rs)
2324
* [Is Power of Two](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/is_power_of_two.rs)
2425
* [Missing Number](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/find_missing_number.rs)
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
//! Hamming Distance
2+
//!
3+
//! This module implements the [Hamming distance](https://en.wikipedia.org/wiki/Hamming_distance)
4+
//! algorithm for both integers and strings.
5+
//!
6+
//! The Hamming distance between two values is the number of positions at which
7+
//! the corresponding symbols differ.
8+
9+
/// Counts the number of set bits (1s) in a 64-bit unsigned integer.
10+
///
11+
/// # Arguments
12+
///
13+
/// * `value` - The number to count set bits in
14+
///
15+
/// # Returns
16+
///
17+
/// The number of set bits in the value
18+
///
19+
/// # Example
20+
///
21+
/// ```
22+
/// // This is a private helper function
23+
/// let value: u64 = 11; // 1011 in binary has 3 set bits
24+
/// ```
25+
fn bit_count(mut value: u64) -> u64 {
26+
let mut count = 0;
27+
while value != 0 {
28+
if value & 1 == 1 {
29+
count += 1;
30+
}
31+
value >>= 1;
32+
}
33+
count
34+
}
35+
36+
/// Calculates the Hamming distance between two unsigned 64-bit integers.
37+
///
38+
/// The Hamming distance is the number of bit positions at which the
39+
/// corresponding bits differ. This is computed by taking the XOR of the
40+
/// two numbers and counting the set bits.
41+
///
42+
/// # Arguments
43+
///
44+
/// * `a` - The first integer
45+
/// * `b` - The second integer
46+
///
47+
/// # Returns
48+
///
49+
/// The number of differing bits between `a` and `b`
50+
///
51+
/// # Example
52+
///
53+
/// ```
54+
/// use the_algorithms_rust::bit_manipulation::hamming_distance;
55+
///
56+
/// let distance = hamming_distance(11, 2);
57+
/// assert_eq!(distance, 2);
58+
/// ```
59+
pub fn hamming_distance(a: u64, b: u64) -> u64 {
60+
bit_count(a ^ b)
61+
}
62+
63+
/// Calculates the Hamming distance between two strings of equal length.
64+
///
65+
/// The Hamming distance is the number of positions at which the
66+
/// corresponding characters differ.
67+
///
68+
/// # Arguments
69+
///
70+
/// * `a` - The first string
71+
/// * `b` - The second string
72+
///
73+
/// # Returns
74+
///
75+
/// The number of differing characters between `a` and `b`
76+
///
77+
/// # Panics
78+
///
79+
/// Panics if the strings have different lengths
80+
///
81+
/// # Example
82+
///
83+
/// ```
84+
/// use the_algorithms_rust::bit_manipulation::hamming_distance_str;
85+
///
86+
/// let distance = hamming_distance_str("1101", "1111");
87+
/// assert_eq!(distance, 1);
88+
/// ```
89+
pub fn hamming_distance_str(a: &str, b: &str) -> u64 {
90+
assert_eq!(
91+
a.len(),
92+
b.len(),
93+
"Strings must have the same length for Hamming distance calculation"
94+
);
95+
96+
a.chars()
97+
.zip(b.chars())
98+
.filter(|(ch_a, ch_b)| ch_a != ch_b)
99+
.count() as u64
100+
}
101+
102+
#[cfg(test)]
103+
mod tests {
104+
use super::*;
105+
106+
#[test]
107+
fn test_bit_count() {
108+
assert_eq!(bit_count(0), 0);
109+
assert_eq!(bit_count(11), 3); // 1011 in binary
110+
assert_eq!(bit_count(15), 4); // 1111 in binary
111+
}
112+
113+
#[test]
114+
fn test_hamming_distance_integers() {
115+
assert_eq!(hamming_distance(11, 2), 2);
116+
assert_eq!(hamming_distance(2, 0), 1);
117+
assert_eq!(hamming_distance(11, 0), 3);
118+
assert_eq!(hamming_distance(0, 0), 0);
119+
}
120+
121+
#[test]
122+
fn test_hamming_distance_strings() {
123+
assert_eq!(hamming_distance_str("1101", "1111"), 1);
124+
assert_eq!(hamming_distance_str("1111", "1111"), 0);
125+
assert_eq!(hamming_distance_str("0000", "1111"), 4);
126+
assert_eq!(hamming_distance_str("alpha", "alphb"), 1);
127+
assert_eq!(hamming_distance_str("abcd", "abcd"), 0);
128+
assert_eq!(hamming_distance_str("dcba", "abcd"), 4);
129+
}
130+
131+
#[test]
132+
#[should_panic(expected = "Strings must have the same length")]
133+
fn test_hamming_distance_strings_different_lengths() {
134+
hamming_distance_str("abc", "abcd");
135+
}
136+
}

src/bit_manipulation/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod counting_bits;
44
mod find_missing_number;
55
mod find_previous_power_of_two;
66
mod find_unique_number;
7+
mod hamming_distance;
78
mod highest_set_bit;
89
mod is_power_of_two;
910
mod n_bits_gray_code;
@@ -19,6 +20,7 @@ pub use self::counting_bits::count_set_bits;
1920
pub use self::find_missing_number::find_missing_number;
2021
pub use self::find_previous_power_of_two::find_previous_power_of_two;
2122
pub use self::find_unique_number::find_unique_number;
23+
pub use self::hamming_distance::{hamming_distance, hamming_distance_str};
2224
pub use self::highest_set_bit::find_highest_set_bit;
2325
pub use self::is_power_of_two::is_power_of_two;
2426
pub use self::n_bits_gray_code::generate_gray_code;

0 commit comments

Comments
 (0)