use crate::errors::LengthMismatchError;
#[inline]
pub fn hamming(a: &str, b: &str) -> Result<u32, LengthMismatchError> {
hamming_iter(a.chars(), b.chars())
}
#[inline]
pub fn hamming_iter<I: IntoIterator<Item = T>, T: PartialEq>(
a: I,
b: I,
) -> Result<u32, LengthMismatchError> {
let mut distance = 0u32;
let mut a_iter = a.into_iter();
let mut b_iter = b.into_iter();
loop {
match (a_iter.next(), b_iter.next()) {
(Some(aa), Some(bb)) => {
if aa != bb {
distance += 1;
}
}
(Some(_), None) | (None, Some(_)) => return Err(LengthMismatchError),
(None, None) => break,
}
}
Ok(distance)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_err_not_equal() {
assert_eq!(hamming("abc", "ab"), Err(LengthMismatchError));
assert_eq!(hamming("abcd", "ab"), Err(LengthMismatchError));
assert_eq!(hamming("ab", "abc"), Err(LengthMismatchError));
assert_eq!(hamming("ab", "abcd"), Err(LengthMismatchError));
}
#[test]
fn test_empty_string() {
assert_eq!(hamming("", ""), Ok(0));
}
#[test]
fn test_basic() {
assert_eq!(hamming("abcdefg", "0bc1ef2"), Ok(3));
}
#[test]
fn test_iter() {
assert_eq!(hamming_iter(1..3, 2..4), Ok(2));
}
}