Skip to main content

debruijn/
neighbors.rs

1use crate::{Kmer, MerImmut};
2
3/// Generate all Hamming distance 1 neighbors of a kmer
4pub struct KmerOneHammingIter<K>
5where
6    K: Kmer,
7{
8    source: K,       // Original kmer from which we need to generate values
9    position: usize, // Index into kmer where last base was mutated
10    char: u8,        // The last base which was used
11}
12
13impl<K> KmerOneHammingIter<K>
14where
15    K: Kmer,
16{
17    /// Create an iterator over all Hamming distance=1 neighbors of `kmer`.
18    pub fn new(kmer: K) -> Self {
19        KmerOneHammingIter {
20            source: kmer,
21            position: 0,
22            char: 0,
23        }
24    }
25}
26
27impl<K> Iterator for KmerOneHammingIter<K>
28where
29    K: Kmer,
30{
31    type Item = K;
32
33    fn next(&mut self) -> Option<Self::Item> {
34        if self.position >= self.source.len() {
35            return None;
36        }
37        let base_at_pos = self.source.get(self.position);
38
39        if self.char >= 4 {
40            self.position += 1;
41            self.char = 0;
42            self.next()
43        } else if base_at_pos == self.char {
44            self.char += 1;
45            self.next()
46        } else {
47            let next_sseq = self.source.set(self.position, self.char);
48            self.char += 1;
49            Some(next_sseq)
50        }
51    }
52}
53
54#[cfg(test)]
55mod test {
56    use super::*;
57    use crate::kmer::Kmer12;
58    use crate::Kmer;
59
60    #[test]
61    fn test_hd1() {
62        let k1 = Kmer12::from_ascii(b"AAAGGGTTTCCC");
63
64        let mut hd1: Vec<_> = KmerOneHammingIter::new(k1).collect();
65        assert_eq!(hd1.len(), 12 * 3);
66
67        hd1.sort();
68        hd1.dedup();
69        assert_eq!(hd1.len(), 12 * 3);
70
71        for k in &hd1 {
72            assert_eq!(k1.hamming_dist(*k), 1);
73        }
74    }
75}