Shell Sort don't working on JavaScript - javascript

I have an code in Java and it works perfect, but the code translated to JavaScript throw an error. The ShellSort method pass a Array to the method.(I am using the console to debug) My code is:
this.shellSort = function(nums)
{
//O contador de tempo inicia aqui
var tempoSS = new Date();
var n = nums.length;
console.log("n = ",n);
var h = n / 2;
console.log("h = ",h);
var c, j;
while (h > 0)
{
for (var i = h; i < n; i++)
{
c = nums[i];
j = i;
while (j >= h && nums[j - h] > c)
{
nums[j] = nums[j - h];
console.log("nums["+j+"] = ",nums[j]);
j = j - h;
console.log("j = ",j);
}
nums[j] = c;
console.log("nums["+j+"] = ",nums[j]);
}
h = h / 2;
console.log("h = ",h);
}
the error is caught is --
[13:52:59.581] ReferenceError: reference to undefined property nums[(j - h)] # file:///C:/Documents%20and%20Settings/erickribeiro/Desktop/www/index.html:240
Test page: dev.erickribeiro.com.br/index.html
The full script is the html page.
What is wrong?

I believe you're getting stuck in an endless loop because h may be a float sometimes. You have to ensure it's an integer (which in Java it is always, since you probably declared it as such):
this.shellSort = function(nums)
{
//O contador de tempo inicia aqui
var tempoSS = new Date();
var n = nums.length;
console.log("n = ",n);
// HERE:
var h = Math.floor(n / 2);
console.log("h = ",h);
var c, j;
while (h > 0)
{
for (var i = h; i < n; i++)
{
c = nums[i];
j = i;
while (j >= h && nums[j - h] > c)
{
nums[j] = nums[j - h];
console.log("nums["+j+"] = ",nums[j]);
j = j - h;
console.log("j = ",j);
}
nums[j] = c;
console.log("nums["+j+"] = ",nums[j]);
}
// AND HERE:
h = Math.floor(h / 2);
console.log("h = ",h);
}
}

Related

Extract last ","

This is my code
function convertToCurr(value) {
var x = value.toString().length;
var z = x % 3;
var a = 0;
if (z == 0) {
a = (x / 3) - 1;
}
else {
a = (x / 3);
}
var last = 0;
var vals = [];
var i;
for (i = 1; i <= a; i++) {
steps = 3;
start = x - steps * i;
end = start + steps;
last = end - steps;
vals.unshift(value.toString().slice(start, end));
}
vals.unshift("R " + value.toString().slice(0, last));
return vals.join();
}
basicIO.write(convertToCurr(input));
context.log.INFO("log data");
}
These are my outputs
{"output":"R 1,000,000,.00","log":["log data"]}
{"output":"R 1,000,.00","log":["log data"]}
I need to exctract the last "," so that the amounts make sense
The most straightforward solution is to perform a String.prototype.replace() on the final join().
function convertToCurr(value) {
var x = value.toString().length;
var z = x % 3;
var a = 0;
if (z == 0) {
a = (x / 3) - 1;
}
else {
a = (x / 3);
}
var last = 0;
var vals = [];
var i;
for (i = 1; i <= a; i++) {
steps = 3;
start = x - steps * i;
end = start + steps;
last = end - steps;
vals.unshift(value.toString().slice(start, end));
}
vals.unshift("R " + value.toString().slice(0, last));
return vals.join().replace(',.', '.');
}
console.log(convertToCurr(10000.75));
console.log(convertToCurr(10.01));
console.log(convertToCurr(1000));
console.log(convertToCurr(7002344));
It should be noted that replace() only replaces a single instance of the substring you provide it in the input string, but this doesn't matter here since ,. only appears in your output string one time.
function convertToCurr(value) {
var x = value.toString().length;
var z = x % 3;
var a = 0;
var combinedString; // holds string value after join
if (z == 0) {
a = x / 3 - 1;
} else {
a = x / 3;
}
var last = 0;
var vals = [];
var i;
for (i = 1; i <= a; i++) {
steps = 3;
start = x - steps * i;
end = start + steps;
last = end - steps;
vals.unshift(value.toString().slice(start, end));
}
vals.unshift("R " + value.toString().slice(0, last));
combinedString = vals.join(); // join array into string
return combinedString.replace(",.", "."); // replace ,. with .
}
console.log(convertToCurr(50000000.15));

Problem on converting HSI to RGB color space and vice versa

I'm trying to implement color complement image processing , since opencv doesnt have rgb to hsi color conversion , i have to do that myself , unfortunately i found a problem.
here's a piece of code where i try to convert rgb to hsi
for( i = 0 ; i < src.rows ; i++){
for( j = 0 ; j < src.cols ; j++){
var pixel = src.ucharPtr(i,j);
r = pixel[0];
g = pixel[1];
b = pixel[2];
intensity = (b+g+r)/3;
var min_val = Math.min(r,g,b);
s = 1 - 3*(min_val/(b + g + r));
if(s < 0.00001)
{
s = 0;
}else if(s > 0.99999){
s = 1;
}
if(s != 0)
{
h = 0.5 * ((r - g) + (r - b)) / Math.sqrt(((r - g)*(r - g)) + ((r - b)*(g - b)));
h = Math.acos(h);
if(b <= g)
{
h = h;
} else{
h = 360 - h;
}
}
pixel[0] = h;
pixel[1] = s;
pixel[2] = intensity;
and here's the code where i try to convert it back to rgb
for(i = 0 ; i < src.rows ; i++){
for(j = 0 ; j < src.cols ; j++){
var pixel = src.ucharPtr(i,j);
h = pixel[0];
s = pixel[1];
intensity = pixel[2];
if(h < 120){
b = intensity*(1-s);
r=intensity*((1.0+((s*Math.cos(h))/(Math.cos(60-h)))));
g=1-(r+b);
}
else if(h < 240){
h -= 120;
r=intensity*(1-s);
g=intensity*((1.0+((s*Math.cos(h))/(Math.cos(60-h)))));
b=1-(r+g);
}
else{
h=h-240;
g=intensity*(1-s);
b=intensity*((1.0+((s*Math.cos(h))/(Math.cos(60-h)))));
r=1-(g+b);
}
pixel[0] = r;
pixel[1] = g;
pixel[2] = b;
}
}
Original Image
HSI Image
Reverse Image
I just followed the RBGtoHSI algorithm and vice versa. am i doing that the right way or there are something i missed ?
Thanks !

Paradoxical Javascript Variable Defining

I am trying to calculate a maths question. It requires the use of variables within variables that loop around.
Here is my JavaScript Code:
var a = m+1;
var b = n+1;
var c = o+1;
var d = p+1;
var e = q+1;
var f = r+1;
var g = s+1;
var h = t+1;
var i = u+1;
var j = v+1;
var l = w+1;
var m = (1+b)/2;
var n = (a+c)/2;
var o = (b+d)/2;
var p = (c+e)/2;
var q = (d+f)/2;
var r = (e+g)/2;
var s = (f+h)/2;
var t = (g+i)/2;
var u = (h+j)/2;
var v = (i+l)/2;
var w = (j+12)/2;
function CalculateA() {
alert(a);
}
The HTML is just a button calling CalculateA() Function.
This results with undefined. Is there a way to properly calculate this or is it not possible with javascript or coding.
Edit
I relize now that this isn't working very well.
Also I ran it through excel with looping calculations and found the answer.
Thanks for all your help anyway.
https://drive.google.com/open?id=0B9I2lCue4HpLZEh3X0NGTUE4YXM
The Excel Calculation ^
You could give all variables a start value of zero to prevent NaN and then call the operations again until a is converging to 12.916666666666651.
function calc() {
a = m + 1;
b = n + 1;
c = o + 1;
d = p + 1;
e = q + 1;
f = r + 1;
g = s + 1;
h = t + 1;
i = u + 1;
j = v + 1;
l = w + 1;
m = (1 + b) / 2;
n = (a + c) / 2;
o = (b + d) / 2;
p = (c + e) / 2;
q = (d + f) / 2;
r = (e + g) / 2;
s = (f + h) / 2;
t = (g + i) / 2;
u = (h + j) / 2;
v = (i + l) / 2;
w = (j + 12) / 2;
console.log(a);
}
var a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0,
ii, letter;
for (ii = 0; ii < 1000; ii++) {
calc();
}
for (ii = 1; ii <= 23; ii++) {
letter = (ii + 9).toString(36);
letter === 'k' || console.log(letter, window[letter]); // k is missing ...
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nothing is impossible in coding. it is returning undefined because 'a' is declared on top where m is not defined and it is "NaN" error -- Not a Number.
The variables end up depending onto each other, which means that your result will always be NaN.
Javascript tries to give you an exact result for the formula, which it can't. What you need for this math issue, is to replace the variables in each term with each other, to get to a result with only 1 variable - I don't think there's a way for you to do that in Javascript with less effort than doing it manually.

Javascript: PI (π) Calculator

Is there a way to calculate pi in Javascript? I know there you can use Math.PI to find pie like this:
var pie = Math.PI;
alert(pie); // output "3.141592653589793"
but this is not accurate. What I want is to be able to calculate it, to have as many digits as you want, not anything like pie = 3.141592.... But still, what I want is not have just have some more digits, but as much as you can (like having one thousand digits, but I need more).
Here is an implementation of a streaming algorithm described by Jeremy Gibbons in Unbounded Spigot Algorithms for the Digits of Pi (2004), Chaper 6:
function * generateDigitsOfPi() {
let q = 1n;
let r = 180n;
let t = 60n;
let i = 2n;
while (true) {
let digit = ((i * 27n - 12n) * q + r * 5n) / (t * 5n);
yield Number(digit);
let u = i * 3n;
u = (u + 1n) * 3n * (u + 2n);
r = u * 10n * (q * (i * 5n - 2n) + r - t * digit);
q *= 10n * i * (i++ * 2n - 1n);
t *= u;
}
}
// Demo
let iter = generateDigitsOfPi();
let output = document.querySelector("div");
(function displayTenNextDigits() {
let digits = "";
for (let i = 0; i < 10; i++) digits += iter.next().value;
output.insertAdjacentHTML("beforeend", digits);
scrollTo(0, document.body.scrollHeight);
requestAnimationFrame(displayTenNextDigits);
})();
div { word-wrap:break-word; font-family: monospace }
<div></div>
I found this code on this website:
mess = "";
Base = Math.pow(10, 11);
cellSize = Math.floor(Math.log(Base) / Math.LN10);
a = Number.MAX_VALUE;
MaxDiv = Math.floor(Math.sqrt(a));
function makeArray(n, aX, Integer) {
var i = 0;
for (i = 1; i < n; i++) aX[i] = null;
aX[0] = Integer
}
function isEmpty(aX) {
var empty = true
for (i = 0; i < aX.length; i++)
if (aX[i]) {
empty = false;
break
}
return empty
}
function Add(n, aX, aY) {
carry = 0
for (i = n - 1; i >= 0; i--) {
aX[i] += Number(aY[i]) + Number(carry);
if (aX[i] < Base) carry = 0;
else {
carry = 1;
aX[i] = Number(aX[i]) - Number(Base)
}
}
}
function Sub(n, aX, aY) {
for (i = n - 1; i >= 0; i--) {
aX[i] -= aY[i];
if (aX[i] < 0) {
if (i > 0) {
aX[i] += Base;
aX[i - 1]--
}
}
}
}
function Mul(n, aX, iMult) {
carry = 0;
for (i = n - 1; i >= 0; i--) {
prod = (aX[i]) * iMult;
prod += carry;
if (prod >= Base) {
carry = Math.floor(prod / Base);
prod -= (carry * Base)
} else carry = 0;
aX[i] = prod
}
}
function Div(n, aX, iDiv, aY) {
carry = 0;
for (i = 0; i < n; i++) {
currVal = Number(aX[i]) + Number(carry * Base);
theDiv = Math.floor(currVal / iDiv);
carry = currVal - theDiv * iDiv;
aY[i] = theDiv
}
}
function arctan(iAng, n, aX) {
iAng_squared = iAng * iAng;
k = 3;
sign = 0;
makeArray(n, aX, 0);
makeArray(n, aAngle, 1);
Div(n, aAngle, iAng, aAngle);
Add(n, aX, aAngle);
while (!isEmpty(aAngle)) {
Div(n, aAngle, iAng_squared, aAngle);
Div(n, aAngle, k, aDivK);
if (sign) Add(n, aX, aDivK);
else Sub(n, aX, aDivK);
k += 2;
sign = 1 - sign
}
mess += "aArctan=" + aArctan + "<br>"
}
function calcPI(numDec) {
var ans = "";
t1 = new Date();
numDec = Number(numDec) + 5;
iAng = new Array(10);
coeff = new Array(10);
arrayLength = Math.ceil(1 + numDec / cellSize);
aPI = new Array(arrayLength);
aArctan = new Array(arrayLength);
aAngle = new Array(arrayLength);
aDivK = new Array(arrayLength);
coeff[0] = 4;
coeff[1] = -1;
coeff[2] = 0;
iAng[0] = 5;
iAng[1] = 239;
iAng[2] = 0;
makeArray(arrayLength, aPI, 0);
makeArray(arrayLength, aAngle, 0);
makeArray(arrayLength, aDivK, 0);
for (var i = 0; coeff[i] != 0; i++) {
arctan(iAng[i], arrayLength, aArctan);
Mul(arrayLength, aArctan, Math.abs(coeff[i]));
if (coeff[i] > 0) Add(arrayLength, aPI, aArctan);
else Sub(arrayLength, aPI, aArctan)
}
Mul(arrayLength, aPI, 4);
sPI = "";
tempPI = "";
for (i = 0; i < aPI.length; i++) {
aPI[i] = String(aPI[i]);
if (aPI[i].length < cellSize && i != 0) {
while (aPI[i].length < cellSize) aPI[i] = "0" + aPI[i]
}
tempPI += aPI[i]
}
for (i = 0; i <= numDec; i++) {
if (i == 0) sPI += tempPI.charAt(i) + ".<br>";
else {
if (document.getElementById("cbCount").checked) addcount = " (" + (i) + ")";
else addcount = "";
if (document.getElementById("cbSpace").checked) thespace = " ";
else thespace = "";
if ((i) % 50 == 0 && i != 0) sPI += tempPI.charAt(i) + addcount + "<br>";
else if (i % 5 == 0) sPI += tempPI.charAt(i) + thespace;
else sPI += tempPI.charAt(i)
}
}
ans += ("PI (" + numDec + ")=" + sPI + "<br>");
ans += ("Win PI=<br>3.1415926535897932384626433832795<br>");
t2 = new Date();
timeTaken = (t2.getTime() - t1.getTime()) / 1000;
ans += "It took: " + timeTaken + " seconds";
var myDiv = document.getElementById("d1");
myDiv.innerHTML = ans
}
<form name="" onsubmit="calcPI(this.t1.value);return false;">
Number of Digits:<br>
<input type="text" name="t1" id="t1" value="100" size="25" maxlength="25">
<br>Add Count:
<input type="checkbox" name="cbCount" id="cbCount" value="" checked="checked">
<br>Add Spaces:
<input type="checkbox" name="cbSpace" id="cbSpace" value="" checked="checked">
<br>
<input type="button" value="Calculate Pi" onclick="calcPI(this.form.t1.value)">
</form>
<div id="d1"></div>
You can approximate the value of π through the use of Monte Carlo simulation. Generate a random X and Y each in the range [-1,1] Then the likelihood (X, Y) is in the unit circle centered at the origin is π/4. More samples yields a better estimate of its value. You can then estimate π by comparing the ratio of samples in the unit circle with the total number of samples and multiply by 4.
this.pi = function(count) {
var inside = 0;
for (var i = 0; i < count; i++) {
var x = random()*2-1;
var y = random()*2-1;
if ((x*x + y*y) < 1) {
inside++
}
}
return 4.0 * inside / count;
}
Here is my implementation using Infinite Series
function calculatePI(iterations = 10000){
let pi = 0;
let iterator = sequence();
for(let i = 0; i < iterations; i++){
pi += 4 / iterator.next().value;
pi -= 4 / iterator.next().value;
}
function* sequence() {
let i = 1;
while(true){
yield i;
i += 2;
}
}
return pi;
}
You can use this for your purpose
Math.PI.toFixed(n)
where n is the number of decimals you wish to display.
It displays the rounded value of pi. It can be considered fairly correct upto 15 decimal places.

Sort an array by the "Levenshtein Distance" with best performance in Javascript

So I have a random javascript array of names...
[#larry,#nicholas,#notch] etc.
They all start with the # symbol. I'd like to sort them by the Levenshtein Distance so that the the ones at the top of the list are closest to the search term. At the moment, I have some javascript that uses jQuery's .grep() on it using javascript .match() method around the entered search term on key press:
(code edited since first publish)
limitArr = $.grep(imTheCallback, function(n){
return n.match(searchy.toLowerCase())
});
modArr = limitArr.sort(levenshtein(searchy.toLowerCase(), 50))
if (modArr[0].substr(0, 1) == '#') {
if (atRes.childred('div').length < 6) {
modArr.forEach(function(i){
atRes.append('<div class="oneResult">' + i + '</div>');
});
}
} else if (modArr[0].substr(0, 1) == '#') {
if (tagRes.children('div').length < 6) {
modArr.forEach(function(i){
tagRes.append('<div class="oneResult">' + i + '</div>');
});
}
}
$('.oneResult:first-child').addClass('active');
$('.oneResult').click(function(){
window.location.href = 'http://hashtag.ly/' + $(this).html();
});
It also has some if statements detecting if the array contains hashtags (#) or mentions (#). Ignore that. The imTheCallback is the array of names, either hashtags or mentions, then modArr is the array sorted. Then the .atResults and .tagResults elements are the elements that it appends each time in the array to, this forms a list of names based on the entered search terms.
I also have the Levenshtein Distance algorithm:
var levenshtein = function(min, split) {
// Levenshtein Algorithm Revisited - WebReflection
try {
split = !("0")[0]
} catch(i) {
split = true
};
return function(a, b) {
if (a == b)
return 0;
if (!a.length || !b.length)
return b.length || a.length;
if (split) {
a = a.split("");
b = b.split("")
};
var len1 = a.length + 1,
len2 = b.length + 1,
I = 0,
i = 0,
d = [[0]],
c, j, J;
while (++i < len2)
d[0][i] = i;
i = 0;
while (++i < len1) {
J = j = 0;
c = a[I];
d[i] = [i];
while(++j < len2) {
d[i][j] = min(d[I][j] + 1, d[i][J] + 1, d[I][J] + (c != b[J]));
++J;
};
++I;
};
return d[len1 - 1][len2 - 1];
}
}(Math.min, false);
How can I work with algorithm (or a similar one) into my current code to sort it without bad performance?
UPDATE:
So I'm now using James Westgate's Lev Dist function. Works WAYYYY fast. So performance is solved, the issue now is using it with source...
modArr = limitArr.sort(function(a, b){
levDist(a, searchy)
levDist(b, searchy)
});
My problem now is general understanding on using the .sort() method. Help is appreciated, thanks.
Thanks!
I wrote an inline spell checker a few years ago and implemented a Levenshtein algorithm - since it was inline and for IE8 I did quite a lot of performance optimisation.
var levDist = function(s, t) {
var d = []; //2d matrix
// Step 1
var n = s.length;
var m = t.length;
if (n == 0) return m;
if (m == 0) return n;
//Create an array of arrays in javascript (a descending loop is quicker)
for (var i = n; i >= 0; i--) d[i] = [];
// Step 2
for (var i = n; i >= 0; i--) d[i][0] = i;
for (var j = m; j >= 0; j--) d[0][j] = j;
// Step 3
for (var i = 1; i <= n; i++) {
var s_i = s.charAt(i - 1);
// Step 4
for (var j = 1; j <= m; j++) {
//Check the jagged ld total so far
if (i == j && d[i][j] > 4) return n;
var t_j = t.charAt(j - 1);
var cost = (s_i == t_j) ? 0 : 1; // Step 5
//Calculate the minimum
var mi = d[i - 1][j] + 1;
var b = d[i][j - 1] + 1;
var c = d[i - 1][j - 1] + cost;
if (b < mi) mi = b;
if (c < mi) mi = c;
d[i][j] = mi; // Step 6
//Damerau transposition
if (i > 1 && j > 1 && s_i == t.charAt(j - 2) && s.charAt(i - 2) == t_j) {
d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost);
}
}
}
// Step 7
return d[n][m];
}
I came to this solution:
var levenshtein = (function() {
var row2 = [];
return function(s1, s2) {
if (s1 === s2) {
return 0;
} else {
var s1_len = s1.length, s2_len = s2.length;
if (s1_len && s2_len) {
var i1 = 0, i2 = 0, a, b, c, c2, row = row2;
while (i1 < s1_len)
row[i1] = ++i1;
while (i2 < s2_len) {
c2 = s2.charCodeAt(i2);
a = i2;
++i2;
b = i2;
for (i1 = 0; i1 < s1_len; ++i1) {
c = a + (s1.charCodeAt(i1) === c2 ? 0 : 1);
a = row[i1];
b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
row[i1] = b;
}
}
return b;
} else {
return s1_len + s2_len;
}
}
};
})();
See also http://jsperf.com/levenshtein-distance/12
Most speed was gained by eliminating some array usages.
Updated: http://jsperf.com/levenshtein-distance/5
The new Revision annihilates all other benchmarks. I was specifically chasing Chromium/Firefox performance as I don't have an IE8/9/10 test environment, but the optimisations made should apply in general to most browsers.
Levenshtein Distance
The matrix to perform Levenshtein Distance can be reused again and again. This was an obvious target for optimisation (but be careful, this now imposes a limit on string length (unless you were to resize the matrix dynamically)).
The only option for optimisation not pursued in jsPerf Revision 5 is memoisation. Depending on your use of Levenshtein Distance, this could help drastically but was omitted due to its implementation specific nature.
// Cache the matrix. Note this implementation is limited to
// strings of 64 char or less. This could be altered to update
// dynamically, or a larger value could be used.
var matrix = [];
for (var i = 0; i < 64; i++) {
matrix[i] = [i];
matrix[i].length = 64;
}
for (var i = 0; i < 64; i++) {
matrix[0][i] = i;
}
// Functional implementation of Levenshtein Distance.
String.levenshteinDistance = function(__this, that, limit) {
var thisLength = __this.length, thatLength = that.length;
if (Math.abs(thisLength - thatLength) > (limit || 32)) return limit || 32;
if (thisLength === 0) return thatLength;
if (thatLength === 0) return thisLength;
// Calculate matrix.
var this_i, that_j, cost, min, t;
for (i = 1; i <= thisLength; ++i) {
this_i = __this[i-1];
for (j = 1; j <= thatLength; ++j) {
// Check the jagged ld total so far
if (i === j && matrix[i][j] > 4) return thisLength;
that_j = that[j-1];
cost = (this_i === that_j) ? 0 : 1; // Chars already match, no ++op to count.
// Calculate the minimum (much faster than Math.min(...)).
min = matrix[i - 1][j ] + 1; // Deletion.
if ((t = matrix[i ][j - 1] + 1 ) < min) min = t; // Insertion.
if ((t = matrix[i - 1][j - 1] + cost) < min) min = t; // Substitution.
matrix[i][j] = min; // Update matrix.
}
}
return matrix[thisLength][thatLength];
};
Damerau-Levenshtein Distance
jsperf.com/damerau-levenshtein-distance
Damerau-Levenshtein Distance is a small modification to Levenshtein Distance to include transpositions. There is very little to optimise.
// Damerau transposition.
if (i > 1 && j > 1 && this_i === that[j-2] && this[i-2] === that_j
&& (t = matrix[i-2][j-2]+cost) < matrix[i][j]) matrix[i][j] = t;
Sorting Algorithm
The second part of this answer is to choose an appropriate sort function. I will upload optimised sort functions to http://jsperf.com/sort soon.
I implemented a very performant implementation of levenshtein distance calculation if you still need this.
function levenshtein(s, t) {
if (s === t) {
return 0;
}
var n = s.length, m = t.length;
if (n === 0 || m === 0) {
return n + m;
}
var x = 0, y, a, b, c, d, g, h, k;
var p = new Array(n);
for (y = 0; y < n;) {
p[y] = ++y;
}
for (; (x + 3) < m; x += 4) {
var e1 = t.charCodeAt(x);
var e2 = t.charCodeAt(x + 1);
var e3 = t.charCodeAt(x + 2);
var e4 = t.charCodeAt(x + 3);
c = x;
b = x + 1;
d = x + 2;
g = x + 3;
h = x + 4;
for (y = 0; y < n; y++) {
k = s.charCodeAt(y);
a = p[y];
if (a < c || b < c) {
c = (a > b ? b + 1 : a + 1);
}
else {
if (e1 !== k) {
c++;
}
}
if (c < b || d < b) {
b = (c > d ? d + 1 : c + 1);
}
else {
if (e2 !== k) {
b++;
}
}
if (b < d || g < d) {
d = (b > g ? g + 1 : b + 1);
}
else {
if (e3 !== k) {
d++;
}
}
if (d < g || h < g) {
g = (d > h ? h + 1 : d + 1);
}
else {
if (e4 !== k) {
g++;
}
}
p[y] = h = g;
g = d;
d = b;
b = c;
c = a;
}
}
for (; x < m;) {
var e = t.charCodeAt(x);
c = x;
d = ++x;
for (y = 0; y < n; y++) {
a = p[y];
if (a < c || d < c) {
d = (a > d ? d + 1 : a + 1);
}
else {
if (e !== s.charCodeAt(y)) {
d = c + 1;
}
else {
d = c;
}
}
p[y] = d;
c = a;
}
h = d;
}
return h;
}
It was my answer to a similar SO question
Fastest general purpose Levenshtein Javascript implementation
Update
A improved version of the above is now on github/npm see
https://github.com/gustf/js-levenshtein
The obvious way of doing this is to map each string to a (distance, string) pair, then sort this list, then drop the distances again. This way you ensure the levenstein distance only has to be computed once. Maybe merge duplicates first, too.
I would definitely suggest using a better Levenshtein method like the one in #James Westgate's answer.
That said, DOM manipulations are often a great expense. You can certainly improve your jQuery usage.
Your loops are rather small in the example above, but concatenating the generated html for each oneResult into a single string and doing one append at the end of the loop will be much more efficient.
Your selectors are slow. $('.oneResult') will search all elements in the DOM and test their className in older IE browsers. You may want to consider something like atRes.find('.oneResult') to scope the search.
In the case of adding the click handlers, we may want to do one better avoid setting handlers on every keyup. You could leverage event delegation by setting a single handler on atRest for all results in the same block you are setting the keyup handler:
atRest.on('click', '.oneResult', function(){
window.location.href = 'http://hashtag.ly/' + $(this).html();
});
See http://api.jquery.com/on/ for more info.
I just wrote an new revision: http://jsperf.com/levenshtein-algorithms/16
function levenshtein(a, b) {
if (a === b) return 0;
var aLen = a.length;
var bLen = b.length;
if (0 === aLen) return bLen;
if (0 === bLen) return aLen;
var len = aLen + 1;
var v0 = new Array(len);
var v1 = new Array(len);
var i = 0;
var j = 0;
var c2, min, tmp;
while (i < len) v0[i] = i++;
while (j < bLen) {
c2 = b.charAt(j++);
v1[0] = j;
i = 0;
while (i < aLen) {
min = v0[i] - (a.charAt(i) === c2 ? 1 : 0);
if (v1[i] < min) min = v1[i];
if (v0[++i] < min) min = v0[i];
v1[i] = min + 1;
}
tmp = v0;
v0 = v1;
v1 = tmp;
}
return v0[aLen];
}
This revision is faster than the other ones. Works even on IE =)

Categories