How can I validate a sentence in a javascript using Levenshtein Distance? - javascript

I am trying to compare two sentences ("Kat" and input "Spat") using Levenshtein Distance. If the sentences are similar enough, I want a "correct" text to appear. The script, which I have copied, works fine, but I am having troubles with the If-statement. I want a "correct" text to appear, if the Levenshtein distance is measured to "2" (As is the case with "Kat" and "Spat"), but I don't know which variable should be set as equal to "2".
//Codes by Jared Stilwell
var matrix;
var first = "Kat";
function levenshteinDistance(a, b) {
if (b.length == 0) return a.length;
matrix = [];
// increment along the first column of each row
for (var i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
// increment each column in the first row
for (var j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
// fill in the rest of the matrix
for (i = 1; i <= b.length; i++) {
for (j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) == a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(
matrix[i - 1][j - 1] + 1, // substitution
Math.min(
matrix[i][j - 1] + 1, // insertion
matrix[i - 1][j] + 1
)
); // deletion
}
}
}
return matrix[b.length][a.length];
}
function updateDistance() {
var second = $(".term-2").val();
$(".js-distance").text(levenshteinDistance(first, second));
}
$(".term-2").on("keyup", function(ev) {
ev.preventDefault();
updateDistance();
});
updateDistance();
//My own part which I can't figure out
function testknap() {
if (matrix == 2) // I CAN'T FIGURE OUT THIS PART?
document.getElementById("correct_text_here").innerHTML = "Correct";
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="js-distance">0</div>
<!-- The distance points -->
<!-- Textform -->
<input class="term-2" value="Spat" placeholder="Skriv her">
<button onclick="testknap()">Tryk</button>
<!-- A submit button -->
<!-- Text which appear if the input is correct -->
<p id="correct_text_here"></p>

Just read the value
function testknap() {
if (document.querySelector(".js-distance").textContent == 2)
document.getElementById("correct_text_here").innerHTML = "Correct";
};
//Codes by Jared Stilwell
var matrix;
var first = "Kat";
function levenshteinDistance(a, b) {
if (b.length == 0) return a.length;
matrix = [];
// increment along the first column of each row
for (var i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
// increment each column in the first row
for (var j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
// fill in the rest of the matrix
for (i = 1; i <= b.length; i++) {
for (j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) == a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(
matrix[i - 1][j - 1] + 1, // substitution
Math.min(
matrix[i][j - 1] + 1, // insertion
matrix[i - 1][j] + 1
)
); // deletion
}
}
}
return matrix[b.length][a.length];
}
function updateDistance() {
var second = $(".term-2").val();
$(".js-distance").text(levenshteinDistance(first, second));
}
$(".term-2").on("keyup", function(ev) {
ev.preventDefault();
updateDistance();
});
updateDistance();
function testknap() {
if (document.querySelector(".js-distance").textContent == 2)
document.getElementById("correct_text_here").innerHTML = "Correct";
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="js-distance">0</div>
<!-- The distance points -->
<!-- Textform -->
<input class="term-2" value="Spat" placeholder="Skriv her">
<button onclick="testknap()">Tryk</button>
<!-- A submit button -->
<!-- Text which appear if the input is correct -->
<p id="correct_text_here"></p>

Related

nested for loops in js, incremented by 2

I am currently trying to solve the xmas tree problem, with internal tree-like shape.
issue is with internal spacing, it supposed to be like: 1, 5, 7, 9. Instead it is 1, 3, 4, 5. I do not know, how to increment s loop by 2 in each loop turn.
/*
*********
**** ****
*** ***
** **
* *
*********
*/
function drawTree(h) {
let n = h + 3;
for (var i = 1; i <= 1; i++) {
var temp = "";
for (var j = 1; j <= n; j++) {
temp = temp + "*";
}
console.log(temp);
}
for (var i = 0; i < h - 2; i++) {
var tree = '';
console.log("\n");
for (var k = 3; k <= h - i; k++) {
tree += "*";
};
tree += "s";
for (var k = 1; k <= i; k++) {
for (var k = 1; k <= i; k++) {
tree += "s";
};
tree += "s";
};
for (var k = 3; k <= h - i; k++) {
tree += "*";
};
console.log(tree);
};
console.log("\n");
let g = h + 3;
for (var i = 1; i <= 1; i++) {
var temp = "";
for (var j = 1; j <= g; j++) {
temp = temp + "*";
}
console.log(temp);
}
};
drawTree(6);
function drawTree(stars, rowLength) {
for (let row = 0; row < rowLength; row++) {
if (row === 0) {
console.log("*".repeat(stars));
} else if(row === rowLength - 1) {
console.log("*".repeat(stars));
} else {
let spaces = 2 * row - 1;
if (spaces > stars) {
spaces = stars;
}
let numStarsInRow = "*".repeat((stars - spaces) / 2);
console.log(numStarsInRow + " ".repeat(spaces) + numStarsInRow);
}
}
}
drawTree(9, 5)
You can implement this by nesting loops over the height and the width of the tree, noting that the output is a * whenever:
it's the first or last row; or
the current x position is less than or equal to the halfway point minus the row number; or
the current x position is greater than or equal to the halfway point plus the row number
For all other cases the output is a space. For example:
function drawTree(height) {
// compute the width of the tree from the height
let width = height % 2 ? height + 2 : height + 3;
// find the halfway point
let half = (width - 1) / 2;
for (let i = 0; i < height; i++) {
let l = '';
for (let j = 0; j < width; j++) {
if (i == 0 || // first row
i == height - 1 || // last row
j <= (half - i) || // left side
j >= (half + i) // right side
) {
l += '*';
}
else {
l += ' ';
}
}
console.log(l);
}
}
drawTree(6);
drawTree(5);

Tic-Tac-Toe in JavaScript with minimax algorithm

I'm trying to implement a Tic-Tac-Toe game using a minimax algorithm for n number of grid size in Javascript.
I have copied the algorithm from geeksforgeeks exactly, but in Javascript the result is not expected and something weird is happening beyond my understanding.
I'm calling the function computerTurn(moves) to make the computer move, and inside it calling the function getBestMove(gridArr, depth, isMax, moves) to get the best move via the minimax algorithm.
In both functions, I'm first checking the empty cell in the grid then assigning it with a specific turn, and then calling the getBestMove function with the new grid. However sometimes the assignment of the grid does not take place and the getBestMove method is called.
Secondly, when I'm printing the grid array in the getBestMove method, it's always printing the same array with only two elements like...
gridArr:- 0:-[1,2,0], 1:-[0,0,0], 2:-[0,0,0]
... and every time the next empty cell is returned as bestMove.
At first, I thought that the same array has been passed to every getBestMove function but when I log the score I'm getting results from the evaluateScore(grid) method (which returns 10 for win, -10 to lose and 0 for draw) returning 10 and -10 as well.
See code below.
In any case, what needs to happen is in each iteration of both functions, when an empty cell is detected the function makes a move i.e assignment of turn into the grid and then pass that grid into the function call.
I'm using 1 for 'X', 2 for '0' and 0 for empty cells in the grid. GRID_LENGTH is the size of row of Tic-Tac-Toe which is 3 for now, and grid is the 2d array for storing X and 0. In the evaluateScore function, WIN_LENGTH is the length to decide winning state, which 3 in this case
This is git repository, which creates the error(s) in question
Thank You all!!
function computerTurn(moves) {
let bestValue = -1000,
bestMove = [];
for (let row = 0; row < GRID_LENGTH; row++) {
for (let col = 0; col < GRID_LENGTH; col++) {
if (grid[row][col] == 0) {
// searching for empty cell
grid[row][col] = 2; // making move
moves++; // increment moves count
let moveValue = getBestMove(grid, 0, false, moves); // checking is this is the best move
moves--;
grid[row][col] = 0;
if (moveValue > bestValue) {
// updating values
bestMove[0] = row;
bestMove[1] = col;
bestValue = moveValue;
}
}
}
}
grid[bestMove[0]][bestMove[1]] = 2;
turn = 'X';
return bestMove;
}
function getBestMove(gridArr, depth, isMax, moves) {
let score = evaluateScore(gridArr);
let arr = gridArr;
if (score == 10 || score == -10) {
return score;
}
if (moves == totalMoves) {
return 0;
}
if (isMax) {
let best = -1000;
for (let i = 0; i < GRID_LENGTH; i++) {
for (let j = 0; j < GRID_LENGTH; j++) {
if (arr[i][j] == 0) {
arr[i][j] = 2;
moves++;
best = Math.max(best, getBestMove(arr, depth + 1, !isMax, moves));
arr[i][j] = 0;
moves--;
}
}
}
return best;
} else {
let best = 1000;
for (let i = 0; i < GRID_LENGTH; i++) {
for (let j = 0; j < GRID_LENGTH; j++) {
if (arr[i][j] == 0) {
arr[i][j] = 1;
moves++;
best = Math.min(best, getBestMove(arr, depth + 1, !isMax, moves));
arr[i][j] = 0;
moves--;
}
}
}
return best;
}
}
function evaluateScore(gridArr) {
let diff = GRID_LENGTH - WIN_LENGTH;
let len = WIN_LENGTH - 1;
for (let i = 0; i < GRID_LENGTH; i++) { // check win for different rows
if (diff == 0) {
let win = true;
for (let j = 0; j < len; j++) {
if (gridArr[i][j] != gridArr[i][j + 1]) {
win = false;
break;
}
}
if (win) {
if (gridArr[i][0] == 1) {
return -10;
} else if (gridArr[i][0] == 2) {
return 10;
}
}
} else {
for (let j = 0; j <= diff; j++) {
let count = 0;
for (let k = j; k < len; k++) {
if ((gridArr[i][k] != gridArr[i][k + 1])) {
count++;
}
if (count == len) {
if (gridArr[i][k] == 1) {
return -10;
} else if (gridArr[i][k] == 2) {
return 10;
}
}
}
}
}
}
for (let i = 0; i < GRID_LENGTH; i++) { // check win for different cols
if (diff == 0) {
let win = true;
for (let j = 0; j < len; j++) {
if (gridArr[j][i] != gridArr[j][i + 1]) {
win = false;
break;
}
}
if (win) {
if (gridArr[0][i] == 1) {
return -10;
} else if (gridArr[0][i] == 2) {
return 10;
}
}
} else {
for (let j = 0; j <= diff; j++) {
let count = 0;
for (let k = j; k < len; k++) {
if ((gridArr[k][i] != gridArr[k][i + 1])) {
count++;
}
if (count == len) {
if (gridArr[k][i] == 1) {
return -10;
} else if (gridArr[k][i] == 2) {
return 10;
}
}
}
}
}
}
let diagonalLength = GRID_LENGTH - WIN_LENGTH;
for (let i = 0; i <= diagonalLength; i++) { // diagonals from left to right
for (let j = 0; j <= diagonalLength; j++) {
let row = i,
col = j;
let win = true;
for (let k = 0; k < len; k++) {
if (gridArr[row][col] != gridArr[row + 1][col + 1]) {
win = false;
break;
}
row++;
col++;
}
if (win) {
if (gridArr[i][j] == 1) {
return -10;
} else if (gridArr[i][j] == 2) {
return 10;
}
}
}
}
let compLen = GRID_LENGTH - diagonalLength - 1;
for (let i = 0; i >= diagonalLength; i--) { // diagonals from right to left
for (let j = GRID_LENGTH - 1; j >= compLen; j--) {
let row = i,
col = j;
let win = true;
for (let k = 0; k < len; k++) {
if (gridArr[row][col] != gridArr[row + 1][col - 1]) {
win = false;
break;
}
row++;
col--;
}
if (win) {
if (gridArr[i][j] == 1) {
return -10;
} else if (gridArr[i][j] == 2) {
return 10;
}
}
}
}
return 0;
}

Error in number sorting code in JavaScript

The following code should convert a string into an array of numbers and sort them in descending order. The purpose is to find a substitution for the sort() method.
Something is wrong. If 7 is placed in the first half of the array (like in the example), the code does not work properly. If you swap 7 for a number bigger than the last one (22 in the example), the code will work fine.
I'm looking to get it to work right regardless of the positioning of the numbers.
var row = '92 43 7 119 51 22';
var row = row.split(' ');
var column = row.map(Number);
function arrangeNum(column) {
for (var i = 0; i <= column.length - 1; i++) {
for (var j = column.length - i; j >= 0; j--) {
if (column[j] > column[j - 1]) {
var temp = column[j];
column[j] = column[j - 1];
column[j - 1] = temp;
}
}
}
return column;
}
console.log(arrangeNum(column));
Something is wrong. If 7 is placed in the first half of the array
(like in the example), the code does not work properly.
It is because of your second-for-loop's initialization of j
Replace
for (var j = column.length - i; j >= 0; j--) {
with
for (var j = column.length - 1; j >= i; j--) {
Notice that j is initialized to column.length - 1, but is only allowed to go as low as i
Demo
function arrangeNum(column) {
for (var i = 0; i <= column.length - 1; i++) {
for (var j = column.length - 1; j >= i; j--) {
if (column[j] > column[j - 1]) {
[column[j], column[j - 1]] = [column[j - 1], column[j]];
}
}
}
return column;
}
console.log( arrangeNum( '92 43 7 119 51 22'.split( /\s+/ ).map( Number ) ) );
The problem you are having is that you implemented the bubble sort wrong.
See this line var j = column.length - i; j >= 0; j--, will cause you to ignore the elements of the array starting from the right-side. Since this is a descending order algo, you need to ignore the elements from the left-side, so this: var j = column.length - 1; j >= i; j--.
I added some console logs to show this below:
See in yellow your algo ignores the first element on the next loop.
Below I added my full correction (you had some other minor issues):
for (var i = 1; i <= column.length; i++) {
for (var j = column.length - i; j >= 0; j--) {
console.log({i,j}, column.map((v,idx) => (idx===j) || (idx===j-1) ? `[${v}]` : v ).join(' '))
if (column[j] > column[j - 1]) {
var temp = column[j];
column[j] = column[j - 1];
column[j - 1] = temp;
console.log({i,j}, ' ',column.map((v,idx) => (idx===j) || (idx===j-1) ? `[[${v}]]` : v ).join(' '))
}
}
}
Here you go, you just needed to reverse the order of execution of the j loop, starting from 0 till column.length - 1
var row = '92 43 7 119 51 22';
var row = row.split(' ')
var column = row.map(Number);
function arrangeNum(column) {
for (var i = 0; i <= column.length - 1; i++) {
for (var j = 0; j <= column.length - i; j++) { // SEE THIS
console.log(column)
if (column[j] > column[j - 1]) {
var temp = column[j];
column[j] = column[j - 1];
column[j - 1] = temp;
}
}
}
return column;
}
console.log(arrangeNum(column))
Pls make change in a code as below.
It will work
var row = '92 43 7 119 51 22';
var row = row.split(' ');
var column = row.map(Number);
function arrangeNum(column) {
for (var i = 0; i <= column.length - 1; i++) {
for (var j = column.length - 1; j >= i; j--) {// see this change
if (column[j] > column[j - 1]) {
var temp = column[j];
column[j] = column[j - 1];
column[j - 1] = temp;
}
}
}
return column;
}
console.log(arrangeNum(column));

Triangle asterisks of for loop

Guys I need your assistance I should accomplish several tasks given by supervisor to make triangle using for loop. But I can't get the exact one. Please help me with that!
Here is an illustration how the final output should look like:
Task 2
input
N (example: N = 5)
output
*
**
***
****
*****
Task 3
input
N (example: N = 5)
output
* * *
* *
* * *
* *
* * *
Task 4
input
N (example: N = 5)
output
*****
* *
* *
* *
*****
and this is my code:
function mixedTriangle (n) {
for (var i = 0; i < n; i++) {
for (var j = 0; j <= i; j++) {
document.write('*');
}
document.write('<br>');
}
}
mixedTriangle(5);
this is my take on it (scaling width with n):
first one you want to walk backwards on the columns so we start at the right side.
for the second function the we switch the pattern for each row other than that it's just using modulus to switch for each column
last one you just need the border which basically means minimum column or row or maximum column or row
<script type="text/javascript">
var fullSign = '*';
var emptySign = ' ';
var newRowSign = '<br>';
function mixedTriangle (n) {
for (var row = 1; row <= n; row++) {
for (var col = n; col > 0; col--) {
if(col <= row)
document.write(fullSign);
else
document.write(emptySign);
}
document.write('<br>');
}
}
function mixedTriangle2(n) {
for (var row = 0; row < n; row++) {
for (var col = 0; col < n; col++) {
if(row % 2 == 0) {
if(col % 2 == 0)
document.write(fullSign);
else
document.write(emptySign);
}
else {
if(col % 2 == 1)
document.write(fullSign);
else
document.write(emptySign);
}
}
document.write(newRowSign);
}
}
function mixedTriangle3(n) {
for (var row = 1; row <= n; row++) {
for (var col = 1; col <= n; col++) {
if(row == 1 || col == 1 || col == n || row == n)
document.write(fullSign);
else
document.write(emptySign);
}
document.write(newRowSign);
}
}
// mixedTriangle(5);
// mixedTriangle2(5);
mixedTriangle3(5);
</script>
//create function
function makeDownwardStairs(height) {
//initialize an empty array inside function.
let pyr = [];
//initialize loop and run a number of times
for (let i = 1; i <= height; i++) {
//update array w/ variable value.
pyr += '#'
//Prints the array to the console
console.log(pyr)
}
}
// calls the function
makeDownwardStairs(5);

Finding the rank of the Given string in list of all possible permutations with Duplicates

I was trying to find the Rank of the given string in the list of permutations and was hoping someone can find the bug.
function permute() {
var W = $('input').val(),
C = [];
for (var i = 0; i < 26; i++) C[i] = 0;
var rank = 1;
for (var i = 0; i < W.length; i++) {
C[W.charCodeAt(i) - 'a'.charCodeAt(0)]++;
}
var repeated= 1;
for (var i = 0; i < C.length; i++) {
if(C[i] > 0) {
repeated *= fact(C[i]);
}
}
if (W !== '') {
for (var i = 0; i < W.length; i++) {
//How many characters which are not used, that come before current character
var count = 0;
for (var j = 0; j < 26; j++) {
if (j == (W.charCodeAt(i) - 'a'.charCodeAt(0))) break;
if (C[j] > 0) count++;
}
C[W.charCodeAt(i) - 'a'.charCodeAt(0)] = 0;
rank += ( count * fact(W.length - i - 1) );
}
rank = rank/ repeated;
}
var pp = 'Rank of :: ' + W + ' -- ' + rank;
$('div').append('<p>' + pp + '</p>');
}
function fact(n) {
if (n == 0 || n == 1) return 1;
else return fact(n - 1) * n;
}
$('button').click(permute);
Check Fiddle
A use case for this might be
bookkeeper is supposed to give a rank of 10743.
Here's the demo:
For each position check how many characters left have duplicates, and use the logic that if you need to permute n things and if 'a' things are similar the number of permutations is n!/a!

Categories