2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -0,0 +1,31 @@
|
|||
function levenshtein(a, b) {
|
||||
var t = [], u, i, j, m = a.length, n = b.length;
|
||||
if (!m) { return n; }
|
||||
if (!n) { return m; }
|
||||
for (j = 0; j <= n; j++) { t[j] = j; }
|
||||
for (i = 1; i <= m; i++) {
|
||||
for (u = [i], j = 1; j <= n; j++) {
|
||||
u[j] = a[i - 1] === b[j - 1] ? t[j - 1] : Math.min(t[j - 1], t[j], u[j - 1]) + 1;
|
||||
} t = u;
|
||||
} return u[n];
|
||||
}
|
||||
|
||||
// tests
|
||||
[ ['', '', 0],
|
||||
['yo', '', 2],
|
||||
['', 'yo', 2],
|
||||
['yo', 'yo', 0],
|
||||
['tier', 'tor', 2],
|
||||
['saturday', 'sunday', 3],
|
||||
['mist', 'dist', 1],
|
||||
['tier', 'tor', 2],
|
||||
['kitten', 'sitting', 3],
|
||||
['stop', 'tops', 2],
|
||||
['rosettacode', 'raisethysword', 8],
|
||||
['mississippi', 'swiss miss', 8]
|
||||
].forEach(function(v) {
|
||||
var a = v[0], b = v[1], t = v[2], d = levenshtein(a, b);
|
||||
if (d !== t) {
|
||||
console.log('levenstein("' + a + '","' + b + '") was ' + d + ' should be ' + t);
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
(() => {
|
||||
'use strict';
|
||||
|
||||
// levenshtein :: String -> String -> Int
|
||||
const levenshtein = (sa, sb) => {
|
||||
const [s1, s2] = [sa.split(''), sb.split('')];
|
||||
|
||||
return last(s2.reduce((ns, c) => {
|
||||
const [n, ns1] = uncons(ns);
|
||||
|
||||
return scanl(
|
||||
(z, [c1, x, y]) =>
|
||||
minimum(
|
||||
[y + 1, z + 1, x + fromEnum(c1 != c)]
|
||||
),
|
||||
n + 1,
|
||||
zip3(s1, ns, ns1)
|
||||
);
|
||||
}, range(0, s1.length)));
|
||||
};
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
// GENERIC FUNCTIONS
|
||||
|
||||
// minimum :: [a] -> a
|
||||
const minimum = xs =>
|
||||
xs.reduce((a, x) => (x < a || a === undefined ? x : a), undefined);
|
||||
|
||||
// fromEnum :: Enum a => a -> Int
|
||||
const fromEnum = x => {
|
||||
const type = typeof x;
|
||||
return type === 'boolean' ? (
|
||||
x ? 1 : 0
|
||||
) : (type === 'string' ? x.charCodeAt(0) : undefined);
|
||||
};
|
||||
|
||||
// uncons :: [a] -> Maybe (a, [a])
|
||||
const uncons = xs => xs.length ? [xs[0], xs.slice(1)] : undefined;
|
||||
|
||||
// scanl :: (b -> a -> b) -> b -> [a] -> [b]
|
||||
const scanl = (f, a, xs) => {
|
||||
for (var lst = [a], lng = xs.length, i = 0; i < lng; i++) {
|
||||
a = f(a, xs[i], i, xs), lst.push(a);
|
||||
}
|
||||
return lst;
|
||||
};
|
||||
|
||||
// zip3 :: [a] -> [b] -> [c] -> [(a,b,c)]
|
||||
const zip3 = (xs, ys, zs) =>
|
||||
xs.slice(0, Math.min(xs.length, ys.length, zs.length))
|
||||
.map((x, i) => [x, ys[i], zs[i]]);
|
||||
|
||||
// last :: [a] -> a
|
||||
const last = xs => xs.length ? xs.slice(-1) : undefined;
|
||||
|
||||
// range :: Int -> Int -> [Int]
|
||||
const range = (m, n) =>
|
||||
Array.from({
|
||||
length: Math.floor(n - m) + 1
|
||||
}, (_, i) => m + i);
|
||||
|
||||
/*********************************************************************/
|
||||
// TEST
|
||||
return [
|
||||
["kitten", "sitting"],
|
||||
["sitting", "kitten"],
|
||||
["rosettacode", "raisethysword"],
|
||||
["raisethysword", "rosettacode"]
|
||||
].map(pair => levenshtein.apply(null, pair));
|
||||
|
||||
// -> [3, 3, 8, 8]
|
||||
})();
|
||||
|
|
@ -0,0 +1 @@
|
|||
[3, 3, 8, 8]
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
function levenshtein(str1, str2) {
|
||||
var m = str1.length,
|
||||
n = str2.length,
|
||||
d = [],
|
||||
i, j;
|
||||
|
||||
if (!m) return n;
|
||||
if (!n) return m;
|
||||
|
||||
for (i = 0; i <= m; i++) d[i] = [i];
|
||||
for (j = 0; j <= n; j++) d[0][j] = j;
|
||||
|
||||
for (j = 1; j <= n; j++) {
|
||||
for (i = 1; i <= m; i++) {
|
||||
if (str1[i-1] == str2[j-1]) d[i][j] = d[i - 1][j - 1];
|
||||
else d[i][j] = Math.min(d[i-1][j], d[i][j-1], d[i-1][j-1]) + 1;
|
||||
}
|
||||
}
|
||||
return d[m][n];
|
||||
}
|
||||
|
||||
console.log(levenshtein("kitten", "sitting"));
|
||||
console.log(levenshtein("stop", "tops"));
|
||||
console.log(levenshtein("rosettacode", "raisethysword"));
|
||||
Loading…
Add table
Add a link
Reference in a new issue