string/
string.rs

1use std::fmt::{Debug};
2use matchete::{Assessor, Resemblance};
3
4#[derive(Debug)]
5struct LevenshteinResembler;
6
7impl Resemblance<String, String> for LevenshteinResembler {
8    fn resemblance(&self, query: &String, candidate: &String) -> f64 {
9        let distance = levenshtein_distance(query, candidate);
10        let max_len = query.len().max(candidate.len());
11        if max_len == 0 { 1.0 } else { 1.0 - (distance as f64 / max_len as f64) }
12    }
13
14    fn perfect(&self, query: &String, candidate: &String) -> bool {
15        query == candidate
16    }
17}
18
19fn levenshtein_distance(a: &str, b: &str) -> usize {
20    let len_a = a.len();
21    let len_b = b.len();
22
23    if len_a == 0 { return len_b; }
24    if len_b == 0 { return len_a; }
25
26    let mut matrix = vec![vec![0; len_b + 1]; len_a + 1];
27
28    for i in 0..=len_a { matrix[i][0] = i; }
29    for j in 0..=len_b { matrix[0][j] = j; }
30
31    for i in 1..=len_a {
32        for j in 1..=len_b {
33            let cost = if a.chars().nth(i - 1) == b.chars().nth(j - 1) { 0 } else { 1 };
34            matrix[i][j] = (matrix[i - 1][j] + 1)
35                .min(matrix[i][j - 1] + 1)
36                .min(matrix[i - 1][j - 1] + cost);
37        }
38    }
39
40    matrix[len_a][len_b]
41}
42
43fn main() {
44    let assessor = Assessor::<String, String>::new()
45        .with(LevenshteinResembler, 1.0)
46        .floor(0.6);
47
48    let query = String::from("hello");
49    let candidates = vec![
50        String::from("hello"),
51        String::from("helo"),
52        String::from("world"),
53    ];
54
55    println!("Basic String Matching Example");
56    println!("============================");
57
58    if let Some(verdict) = assessor.champion(&query, &candidates) {
59        println!("Champion found:");
60        println!("  Resemblance: {:.2}", verdict.resemblance);
61        println!("  Candidate: {}", verdict.candidate);
62        println!("  Perfect: {}", verdict.perfect);
63        println!("  Disposition: {:?}", assessor.disposition(&query, &verdict.candidate));
64    } else {
65        println!("No viable candidate found above floor threshold");
66    }
67
68    // Show all candidates for comparison
69    println!("\nAll Candidates Analysis");
70    println!("======================");
71
72    for candidate in &candidates {
73        let verdict = assessor.verdict(&query, candidate);
74        let disposition = assessor.disposition(&query, candidate);
75        println!("'{}': resemblance={:.2}, disposition={:?}",
76                 candidate, verdict.resemblance, disposition);
77    }
78}