mod helpers;
use crate::number::UInt;
use super::Penalties;
pub use helpers::{
_x_to_y, aligned_x_to_y, aligned_x_to_y_no_sub, apply_edits, compute_edits, compute_table, trace_back_iterative,
trace_back_recursive, unaligned_x_to_y, x_to_y_alignment, Edit,
};
pub fn nw_distance_custom<U: UInt>(penalties: Penalties<U>) -> impl Fn(&str, &str) -> U {
move |x: &str, y: &str| compute_table(x, y, penalties)[y.len()][x.len()].0
}
#[must_use]
pub fn nw_distance<U: UInt>(x: &str, y: &str) -> U {
compute_table(x, y, Penalties::default())[y.len()][x.len()].0
}
pub fn edits_recursive_custom<U: UInt>(penalties: Penalties<U>) -> impl Fn(&str, &str) -> ([Vec<Edit>; 2], U) {
move |x: &str, y: &str| {
let table = compute_table(x, y, penalties);
let (aligned_x, aligned_y) = trace_back_recursive(&table, [x, y]);
(
[
unaligned_x_to_y(&aligned_x, &aligned_y),
unaligned_x_to_y(&aligned_y, &aligned_x),
],
table[y.len()][x.len()].0,
)
}
}
#[must_use]
pub fn edits_recursive<U: UInt>(x: &str, y: &str) -> ([Vec<Edit>; 2], U) {
let table = compute_table(x, y, Penalties::default());
let (aligned_x, aligned_y) = trace_back_recursive(&table, [x, y]);
(
[
unaligned_x_to_y(&aligned_x, &aligned_y),
unaligned_x_to_y(&aligned_y, &aligned_x),
],
table[y.len()][x.len()].0,
)
}
pub fn edits_iterative_custom<U: UInt>(penalties: Penalties<U>) -> impl Fn(&str, &str) -> ([Vec<Edit>; 2], U) {
move |x: &str, y: &str| {
let table = compute_table(x, y, penalties);
let (aligned_x, aligned_y) = trace_back_iterative(&table, [x, y]);
(
[
unaligned_x_to_y(&aligned_x, &aligned_y),
unaligned_x_to_y(&aligned_y, &aligned_x),
],
table[y.len()][x.len()].0,
)
}
}
#[must_use]
pub fn edits_iterative<U: UInt>(x: &str, y: &str) -> ([Vec<Edit>; 2], U) {
let table = compute_table(x, y, Penalties::default());
let (aligned_x, aligned_y) = trace_back_iterative(&table, [x, y]);
(
[
unaligned_x_to_y(&aligned_x, &aligned_y),
unaligned_x_to_y(&aligned_y, &aligned_x),
],
table[y.len()][x.len()].0,
)
}
#[cfg(test)]
mod tests {
use super::nw_distance;
#[test]
fn distance() {
let x = "NAJIBEATSPEPPERS".to_string();
let y = "NAJIBPEPPERSEATS".to_string();
let d: u8 = nw_distance(&x, &y);
assert_eq!(d, 8);
let x = "NOTGUILTY".to_string();
let y = "NOTGUILTY".to_string();
let d: u8 = nw_distance(&x, &y);
assert_eq!(d, 0);
}
}