1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//! Levenshtein distance and ratio algorithms.
//!
//! These are implemented from scratch — the library has zero external
//! dependencies and this module must not introduce any.
//!
//! # Algorithms
//!
//! - [`levenshtein_distance`] — the classic edit distance (insertions,
//! deletions, substitutions each cost 1).
//! - [`levenshtein_ratio`] — a normalised similarity score in `[0.0, 1.0]`
//! derived from the distance. Two identical strings score `1.0`; two
//! completely different strings of maximum length score `0.0`.
// ---------------------------------------------------------------------------
// Distance
// ---------------------------------------------------------------------------
/// Compute the Levenshtein edit distance between two strings.
///
/// The distance counts the minimum number of single-character edits
/// (insertions, deletions, or substitutions) required to transform `a` into
/// `b`.
///
/// The implementation uses two rolling rows of a standard dynamic-programming
/// matrix so memory is O(min(|a|, |b|)) rather than O(|a| · |b|).
///
/// Both strings are treated as sequences of bytes. All inputs in this library
/// are ASCII (the caller lowercases before calling), so byte-level comparisons
/// are correct and cheaper than char-level ones.
///
/// # Examples
///
/// ```
/// use partial_date::levenshtein::levenshtein_distance;
///
/// assert_eq!(levenshtein_distance("kitten", "sitting"), 3);
/// assert_eq!(levenshtein_distance("", "abc"), 3);
/// assert_eq!(levenshtein_distance("abc", "abc"), 0);
/// assert_eq!(levenshtein_distance("march", "mrach"), 2);
/// ```
// ---------------------------------------------------------------------------
// Ratio
// ---------------------------------------------------------------------------
/// Compute the normalised Levenshtein similarity ratio between two strings.
///
/// The ratio is defined as:
///
/// ```text
/// ratio = 1.0 - distance(a, b) / max(len(a), len(b))
/// ```
///
/// and lies in the range `[0.0, 1.0]`:
///
/// - `1.0` — the strings are identical (or both empty).
/// - `0.0` — the strings are completely different (distance equals the length
/// of the longer string).
///
/// # Examples
///
/// ```
/// use partial_date::levenshtein::levenshtein_ratio;
///
/// assert!((levenshtein_ratio("march", "march") - 1.0).abs() < f32::EPSILON);
/// assert!((levenshtein_ratio("mrach", "march") - 0.6).abs() < f32::EPSILON);
/// assert!((levenshtein_ratio("january","jauary") - (6.0/7.0)).abs() < f32::EPSILON);
/// ```