minor update to types
This commit is contained in:
1 parent
726104fd54
commit
6b24262927
1 file changed
+35
-15
+35
-15
@@ -1,6 +1,10 @@
|
|||||||
//! # Levenshtein Distance
|
//! # Levenshtein Distance
|
||||||
//! This is a simple implementation of the Levenshtein distance algorithm with operations.
|
//! This is a simple implementation of the Levenshtein distance algorithm with operations.
|
||||||
|
|
||||||
|
/// costs for different edit operations
|
||||||
|
///
|
||||||
|
/// each with the letters involved: so you can further tweak the cost in ur own [`CustomCost`]s impl
|
||||||
|
/// position? idk
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum EditOperation {
|
pub enum EditOperation {
|
||||||
Insert { char: char }, // Insert a character from the target string
|
Insert { char: char }, // Insert a character from the target string
|
||||||
@@ -10,9 +14,9 @@ pub enum EditOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct EditCost {
|
pub struct EditCost {
|
||||||
pub insert: usize,
|
pub insert: i32,
|
||||||
pub delete: usize,
|
pub delete: i32,
|
||||||
pub substitute: usize,
|
pub substitute: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for EditCost {
|
impl Default for EditCost {
|
||||||
@@ -26,7 +30,7 @@ impl Default for EditCost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EditCost {
|
impl EditCost {
|
||||||
pub fn new(insert: usize, delete: usize, substitute: usize) -> Self {
|
pub fn new(insert: i32, delete: i32, substitute: i32) -> Self {
|
||||||
EditCost {
|
EditCost {
|
||||||
insert,
|
insert,
|
||||||
delete,
|
delete,
|
||||||
@@ -34,13 +38,13 @@ impl EditCost {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// custom cost for each [`EditOperation`]s operation
|
||||||
pub trait CustomCost {
|
pub trait CustomCost {
|
||||||
fn cost(&self, operation: &EditOperation) -> usize;
|
fn cost(&self, operation: &EditOperation) -> i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CustomCost for EditCost {
|
impl CustomCost for EditCost {
|
||||||
fn cost(&self, operation: &EditOperation) -> usize {
|
fn cost(&self, operation: &EditOperation) -> i32 {
|
||||||
match operation {
|
match operation {
|
||||||
EditOperation::Insert { .. } => self.insert,
|
EditOperation::Insert { .. } => self.insert,
|
||||||
EditOperation::Delete { .. } => self.delete,
|
EditOperation::Delete { .. } => self.delete,
|
||||||
@@ -49,11 +53,13 @@ impl CustomCost for EditCost {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// is this the main struct
|
||||||
|
///
|
||||||
|
/// cost of operation and the operation itself
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct CostOperation {
|
pub struct CostOperation {
|
||||||
cost: usize,
|
pub cost: i32,
|
||||||
operation: Option<EditOperation>,
|
pub operation: Option<EditOperation>,
|
||||||
}
|
}
|
||||||
// absolutely phenomenal naming
|
// absolutely phenomenal naming
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
@@ -76,12 +82,14 @@ impl Display for CostOperation {
|
|||||||
write!(f, "Cost: {}, Operation: {:#?}", self.cost, self.operation)
|
write!(f, "Cost: {}, Operation: {:#?}", self.cost, self.operation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// returns the distance + the dp table for who needs it
|
||||||
|
///
|
||||||
|
/// this the slow version yes
|
||||||
pub fn levenshtein_with_operations(
|
pub fn levenshtein_with_operations(
|
||||||
str1: &str,
|
str1: &str,
|
||||||
str2: &str,
|
str2: &str,
|
||||||
cost_calc: &impl CustomCost,
|
cost_calc: &impl CustomCost,
|
||||||
) -> (usize, Vec<Vec<CostOperation>>) {
|
) -> (i32, Vec<Vec<CostOperation>>) {
|
||||||
let len1 = str1.len();
|
let len1 = str1.len();
|
||||||
let len2 = str2.len();
|
let len2 = str2.len();
|
||||||
let mut dp = vec![
|
let mut dp = vec![
|
||||||
@@ -100,7 +108,7 @@ pub fn levenshtein_with_operations(
|
|||||||
// Fill the base cases
|
// Fill the base cases
|
||||||
for i in 0..=len1 {
|
for i in 0..=len1 {
|
||||||
dp[i][0] = CostOperation {
|
dp[i][0] = CostOperation {
|
||||||
cost: i,
|
cost: i as i32,
|
||||||
operation: if i > 0 {
|
operation: if i > 0 {
|
||||||
Some(EditOperation::Delete {
|
Some(EditOperation::Delete {
|
||||||
char: chars1[i - 1],
|
char: chars1[i - 1],
|
||||||
@@ -112,7 +120,7 @@ pub fn levenshtein_with_operations(
|
|||||||
}
|
}
|
||||||
for j in 0..=len2 {
|
for j in 0..=len2 {
|
||||||
dp[0][j] = CostOperation {
|
dp[0][j] = CostOperation {
|
||||||
cost: j,
|
cost: j as i32,
|
||||||
operation: if j > 0 {
|
operation: if j > 0 {
|
||||||
Some(EditOperation::Insert {
|
Some(EditOperation::Insert {
|
||||||
char: chars2[j - 1],
|
char: chars2[j - 1],
|
||||||
@@ -167,6 +175,9 @@ pub fn levenshtein_with_operations(
|
|||||||
(dp[len1][len2].cost, dp)
|
(dp[len1][len2].cost, dp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///extract the optimized edit sequence from the dp table
|
||||||
|
///
|
||||||
|
/// strs there just for the len() lmfao
|
||||||
pub fn edit_sequence(dp: &[Vec<CostOperation>], str1: &str, str2: &str) -> Vec<EditOperation> {
|
pub fn edit_sequence(dp: &[Vec<CostOperation>], str1: &str, str2: &str) -> Vec<EditOperation> {
|
||||||
let mut i = str1.len();
|
let mut i = str1.len();
|
||||||
let mut j = str2.len();
|
let mut j = str2.len();
|
||||||
@@ -199,6 +210,9 @@ pub fn edit_sequence(dp: &[Vec<CostOperation>], str1: &str, str2: &str) -> Vec<E
|
|||||||
funny.reverse();
|
funny.reverse();
|
||||||
funny
|
funny
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// alignment
|
||||||
|
/// is ass dont use
|
||||||
pub fn generate_alignment(
|
pub fn generate_alignment(
|
||||||
str1: &str,
|
str1: &str,
|
||||||
str2: &str,
|
str2: &str,
|
||||||
@@ -246,11 +260,16 @@ pub fn generate_alignment(
|
|||||||
(aligned_str1, aligned_str2)
|
(aligned_str1, aligned_str2)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn levenstein_distance(str1: &str, str2: &str, cost: &EditCost) -> (usize, Vec<EditOperation>) {
|
/// calculate distance, also get u the [`edit_sequence`]
|
||||||
|
/// use this one
|
||||||
|
///
|
||||||
|
/// what this does is call this ass [`levenshtein_with_operations`] and then the [`edit_sequence`] from the generated dp table
|
||||||
|
pub fn levenstein_distance(str1: &str, str2: &str, cost: &EditCost) -> (i32, Vec<EditOperation>) {
|
||||||
let (c, d) = levenshtein_with_operations(str1, str2, cost);
|
let (c, d) = levenshtein_with_operations(str1, str2, cost);
|
||||||
(c, edit_sequence(&d, str1, str2))
|
(c, edit_sequence(&d, str1, str2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// get source str from [`edit_sequence`]
|
||||||
pub fn reconstruct_from(vector: &Vec<EditOperation>) -> String {
|
pub fn reconstruct_from(vector: &Vec<EditOperation>) -> String {
|
||||||
let mut funny = String::new();
|
let mut funny = String::new();
|
||||||
for operation in vector {
|
for operation in vector {
|
||||||
@@ -270,6 +289,7 @@ pub fn reconstruct_from(vector: &Vec<EditOperation>) -> String {
|
|||||||
funny
|
funny
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// get changed str from [`edit_sequence`]
|
||||||
pub fn reconstruct_to(vector: &Vec<EditOperation>) -> String {
|
pub fn reconstruct_to(vector: &Vec<EditOperation>) -> String {
|
||||||
let mut funny = String::new();
|
let mut funny = String::new();
|
||||||
for operation in vector {
|
for operation in vector {
|
||||||
|
|||||||
Reference in new issue
Block a user