1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//! Module for `Counting Point Mutations`

use RosalindResult;
use RosalindError::HammingStringsLengthError;

/// This function calculates Hamming distance between `s` and `t`
///
/// # Examples
/// ```
/// use rosalind::RosalindError::HammingStringsLengthError;
/// use rosalind::hamm::*;
///
/// let s = "GAGCCTACTAACGGGAT";
/// let t = "CATCGTAATGACGGCCT";
/// assert_eq!(hamming_distance(s, t).unwrap(), 7);
/// assert_eq!(hamming_distance("G", "").unwrap_err(), HammingStringsLengthError);
/// ```
pub fn hamming_distance(s: &str, t: &str) -> RosalindResult<u16> {
  if s.len() != t.len() { return Err(HammingStringsLengthError); }

  let s_iter = s.chars();
  let t_iter = t.chars();

  let distance: u16 = s_iter.zip(t_iter).fold(0, |mut d, (sc, tc)| {
    if sc != tc { d += 1; }
    d
  });

  Ok(distance)
}

#[cfg(test)]
mod tests {
  use super::hamming_distance;
  use super::super::RosalindError::HammingStringsLengthError;

  #[test]
  fn it_should_return_hamming_distance() {
    let s = "GAGCCTACTAACGGGAT";
    let t = "CATCGTAATGACGGCCT";
    assert_eq!(hamming_distance(s, t).unwrap(), 7);
  }

  #[test]
  fn it_should_return_error_when_strings_have_different_length() {
    assert_eq!(hamming_distance("G", "").unwrap_err(), HammingStringsLengthError);
  }
}