Skip to content

Commit

Permalink
Merge pull request mgechev#87 from deniskyashif/levenshtein-distance-…
Browse files Browse the repository at this point in the history
…tuning-and-tests

Optimized Levenshtein distance algorithm and added unit tests.
  • Loading branch information
mgechev committed Sep 5, 2015
2 parents 766c111 + 9f2c410 commit a88c0b9
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 14 deletions.
38 changes: 24 additions & 14 deletions src/others/levenshtein-distance.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,31 @@

var levenshteinDistance = (function () {

function levenshteinDistance(s, ls, t, lt) {
if (ls === 0) {
return lt;
}
if (lt === 0) {
return ls;
function levenshteinDistance (s, ls, t, lt) {
var memo = [];
var currRowMemo;
var i;
var k;

for (k = 0; k <= lt; k += 1) {
memo[k] = k;
}
var cost;
if (s[ls - 1] === t[lt - 1]) {
cost = 0;
} else {
cost = 1;

for (i = 1; i <= ls; i += 1) {
currRowMemo = [i];

for (k = 1; k <= lt; k += 1) {
currRowMemo[k] = Math.min(
currRowMemo[k - 1] + 1,
memo[k] + 1,
memo[k - 1] + (s[i - 1] !== t[k - 1] ? 1 : 0)
);
}

memo = currRowMemo;
}
return Math.min(levenshteinDistance(s, ls - 1, t, lt) + 1,
levenshteinDistance(s, ls, t, lt - 1) + 1,
levenshteinDistance(s, ls - 1, t, lt - 1) + cost);

return memo[lt];
}

/**
Expand Down Expand Up @@ -49,3 +58,4 @@
exports.levenshteinDistance = levenshteinDistance;

}(typeof exports === 'undefined' ? window : exports));

58 changes: 58 additions & 0 deletions test/others/levenshtein-distance.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
'use strict';

var mod = require('../../src/others/levenshtein-distance.js');
var levenshteinDistance = mod.levenshteinDistance;

describe('Levenstein\'s minimum edit distance algorithm', function () {
it('should be defined', function () {
expect(levenshteinDistance).toBeDefined();
});

it('"" -> "" should return 0.', function () {
expect(levenshteinDistance('', '')).toBe(0);
});

it('"T" -> "" should return 1.', function () {
expect(levenshteinDistance('T', '')).toBe(1);
});

it('"cake" -> "rake" should return 1.', function () {
expect(levenshteinDistance('cake', 'rake')).toBe(1);
});

it('"Sofia" -> "Sof" should return 2.', function () {
expect(levenshteinDistance('Sofia', 'Sof')).toBe(2);
});

it('"kitten" -> "sitting" should return 3', function () {
expect(levenshteinDistance('kitten', 'sitting')).toBe(3);
});

it('"google" -> "lookat" should return 4.', function () {
expect(levenshteinDistance('google', 'lookat')).toBe(4);
});

it('"emacs" -> "vim" should return 5.', function () {
expect(levenshteinDistance('emacs', 'vim')).toBe(5);
});

it('"coffee" -> "cocoa" should return 4.', function () {
expect(levenshteinDistance('coffee', 'cocoa')).toBe(4);
});

it('"Munich" -> "Muenchen" should return 4.', function () {
expect(levenshteinDistance('Munich', 'Muenchen')).toBe(4);
});

it('"rosebud" -> "budrose" should return 6.', function () {
expect(levenshteinDistance('rosebud', 'budrose')).toBe(6);
});

it('"decided" -> "decisive" should return 4.', function () {
expect(levenshteinDistance('decided', 'decisive')).toBe(4);
});

it('"similar" -> "simile" should return 2.', function () {
expect(levenshteinDistance('similar', 'simile')).toBe(2);
});
});

0 comments on commit a88c0b9

Please sign in to comment.