pub fn typos_from_score_matrix(score_matrix: &[&[u16]]) -> u16 {
let mut typo_count = 0;
let mut score = 0;
let mut positions = 0;
let last_column = score_matrix.last().unwrap();
for (idx, &row_score) in last_column.iter().enumerate() {
if row_score > score {
score = row_score;
positions = idx;
}
}
let mut col_idx = score_matrix.len() - 1;
let mut row_idx: usize = positions;
while col_idx > 0 {
if row_idx == 0 {
typo_count += 1;
col_idx -= 1;
continue;
}
let diag = score_matrix[col_idx - 1][row_idx - 1];
let left = score_matrix[col_idx - 1][row_idx];
let up = score_matrix[col_idx][row_idx - 1];
if diag >= left && diag >= up {
if diag >= score {
typo_count += 1;
}
row_idx -= 1;
col_idx -= 1;
score = diag;
} else if left >= up {
typo_count += 1;
col_idx -= 1;
score = left;
} else {
row_idx -= 1;
score = up;
}
}
if col_idx == 0 && score == 0 {
typo_count += 1;
}
typo_count
}
#[cfg(test)]
mod tests {
use super::super::smith_waterman;
use super::typos_from_score_matrix;
fn get_typos(needle: &str, haystack: &str) -> u16 {
let (_, score_matrix) = smith_waterman(needle, haystack);
let score_matrix_ref = score_matrix
.iter()
.map(|v| v.as_slice())
.collect::<Vec<_>>();
typos_from_score_matrix(&score_matrix_ref)
}
#[test]
fn test_typos_basic() {
assert_eq!(get_typos("a", "abc"), 0);
assert_eq!(get_typos("b", "abc"), 0);
assert_eq!(get_typos("c", "abc"), 0);
assert_eq!(get_typos("ac", "abc"), 0);
assert_eq!(get_typos("d", "abc"), 1);
assert_eq!(get_typos("da", "abc"), 1);
assert_eq!(get_typos("dc", "abc"), 1);
assert_eq!(get_typos("ad", "abc"), 1);
assert_eq!(get_typos("adc", "abc"), 1);
assert_eq!(get_typos("add", "abc"), 2);
assert_eq!(get_typos("ddd", "abc"), 3);
assert_eq!(get_typos("ddd", ""), 3);
assert_eq!(get_typos("d", ""), 1);
}
}