|
| 1 | +let length = s => Js.String.length(s) |
| 2 | +let minimum = (a, b, c) => min(a, min(b, c)) |
| 3 | + |
| 4 | +/* |
| 5 | + * Levenshtein distance |
| 6 | + * Translated from OCaml example in Rosetta Code |
| 7 | + * https://rosettacode.org/wiki/Levenshtein_distance#OCaml |
| 8 | + * https://en.wikipedia.org/wiki/Levenshtein_distance |
| 9 | + */ |
| 10 | +let levenshtein = (s, t) => { |
| 11 | + let first = String.length(s) |
| 12 | + and second = String.length(t) |
| 13 | + let matrix = Array.make_matrix(first + 1, second + 1, 0) |
| 14 | + |
| 15 | + for i in 0 to first { |
| 16 | + matrix[i][0] = i |
| 17 | + } |
| 18 | + |
| 19 | + for j in 0 to second { |
| 20 | + matrix[0][j] = j |
| 21 | + } |
| 22 | + |
| 23 | + for j in 1 to second { |
| 24 | + for i in 1 to first { |
| 25 | + if String.get(s, i - 1) == String.get(t, j - 1) { |
| 26 | + matrix[i][j] = matrix[i - 1][j - 1] |
| 27 | + } else { |
| 28 | + matrix[i][j] = minimum(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + 1) |
| 29 | + } |
| 30 | + } |
| 31 | + } |
| 32 | + |
| 33 | + matrix[first][second] |
| 34 | +} |
| 35 | + |
| 36 | +let similarity = (s1, s2) => { |
| 37 | + let (longer, shorter) = switch (s1, s2) { |
| 38 | + | (first, second) when length(first) < length(second) => (second, first) |
| 39 | + | (first, second) => (first, second) |
| 40 | + } |
| 41 | + |
| 42 | + let longerLength = length(longer) |
| 43 | + |
| 44 | + switch longerLength { |
| 45 | + | 0 => 1.0 |
| 46 | + | _ => |
| 47 | + (float_of_int(longerLength) -. float_of_int(levenshtein(longer, shorter))) /. |
| 48 | + float_of_int(longerLength) |
| 49 | + } |
| 50 | +} |
0 commit comments