Search words in array based on few words - javascript

Hi I have a problem how to search for words containing at least part of a word. What I mean words that have word I find in array javascript without built-in function except only PUSH.
This task requires no index.of, slice, substr, substring, regex etc. Only PUSH
This my code so far:
function wordsChecker(sentences, search) {
var result = []
for (var i = 0; i < sentences.length; i++) {
var isCheck = false
for (var j = 0; j < sentences.length; j++) {
for (var k = 0; k < search.length; k++) {
if (sentences[i][j] == search[k]) {
isCheck = true
}
}
}
if (isCheck == true) {
result.push(sentences[i])
}
}
return result
}
console.log(wordsChecker(['broom, room, rox, show room, stroom, root, rote, brother'], 'roo'))
//expected output : [broom, room, show room, stroom, root]
Thanks in advance

At the first you should make correct array. I hope this code work for you
function wordsChecker(sentences, search) {
var result = [], k = 0;
for (var i = 0; i < sentences.length; i++) {
var isCheck = false;
for (var j = 0; j < sentences[i].length; j++) {
while (k < search.length) {
if (sentences[i][j] == search[k]) {
isCheck = true;
k++;
break;
}
else {
isCheck = false;
k = 0;
break;
}
}
}
if (isCheck === true && k === search.length) {
result.push(sentences[i]);
k = 0;
}
}
return result;
}
console.log(wordsChecker(['broom', 'room', 'rox', 'show room', 'stroom', 'root', 'rote', 'brother'], 'roo'));

Related

why does return statement not break recursive for loop in Javascript

Please i am trying to build a Sudoku solver in JavaScript but i face a problem when i get to the solve function, the recursive loop doesn't stop when the board is full. It executes till the end even after finding the solution. Please I'll be grateful if i can get some help. Here is what i tried doing:
class SudokuSolver {
// convert puzzle string to 2D array
boardParser(puzzleString) {
var board = [];
var i, j;
for (i = 0; i < 81; i += 9) {
var boardRow = [];
for (j = 0; j < 9; j++) {
boardRow.push(puzzleString.charAt(i + j));
}
board.push(boardRow)
}
// console.log(board);
return board;
}
// Look for empty space on board (empty space = ".")
// return [row, col] if empty space found
// return [-1,-1] if no empty space found (board is full)
getDot(board) {
var i, j;
for (i = 0; i < 9; i++) {
for (j = 0; j < 9; j++) {
if (board[i][j] == ".") {
return [i, j];
}
}
}
return [-1, -1];
}
checkRowPlacement(board, row, column, value) {
var i;
for (i = 0; i < 9; i++) {
if (board[row][i] == value) {
// console.log("row check false");
return {
valid: false
};
}
}
// console.log("row check true");
return {
valid: true
}
}
checkColPlacement(board, row, column, value) {
var i;
for (i = 0; i < 9; i++) {
if (board[i][column] == value) {
// console.log("col check false")
return {
valid: false
}
}
}
// console.log("col check true")
return {
valid: true
};
}
checkRegionPlacement(board, row, column, value) {
var i, j;
var regRow = Math.floor(row / 3) * 3;
var regCol = Math.floor(column / 3) * 3;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
if (board[regRow + i][regCol + j] == value) {
// console.log("reg check false")
return {
valid: false
}
}
}
}
// console.log("reg check true");
return {
valid: true
}
}
checkvalue(board, row, column, value) {
var rowCheck = this.checkRowPlacement(board, row, column, value).valid
var colCheck = this.checkColPlacement(board, row, column, value).valid
var regCheck = this.checkRegionPlacement(board, row, column, value).valid
// console.log(rowCheck, colCheck, regCheck);
if (rowCheck && colCheck && regCheck) {
// console.log(true)
return true;
}
// console.log(false)
return false;
}
// convert 2D array back to string
stringifyBoard(board) {
var string = ""
var i, j;
for (i = 0; i < 9; i++) {
for (j = 0; j < 9; j++) {
string += board[i][j];
}
}
// console.log(string);
return string;
}
// check for any more empty spaces
solved(board) {
var i, j;
if (this.getDot(board)[0] == -1) {
return true
}
return false
}
solve(puzzleString) {
var board = this.boardParser(puzzleString)
var emptySpot = this.getDot(board);
var row = emptySpot[0];
var column = emptySpot[1];
// full board condition
if (this.solved(board)) {
return puzzleString;
}
for (var i = 1; i <= 9; i++) {
if (this.checkvalue(board, row, column, i)) {
board[row][column] = i;
var boardString = this.stringifyBoard(board);
this.solve(boardString);
}
}
// if board is unsolvable return false
return false;
}
}
const input = '5..91372.3...8.5.9.9.25..8.68.47.23...95..46.7.4.....5.2.......4..8916..85.72...3';
console.log(new SudokuSolver().solve(input));
it returns false, but the puzzle string is valid and also when i console log in the full board condition it shows the solved string but doesn't return it.
So once the board is solved and if this.solved(board) returns true, you are returning the solved board. But this is only at the last level of recursion chain. You need to check at every level of recursion if this particular move reaches a solved board state. Hence, validate the result of the next level and if it returns a solved board, return the solved board from the current level too. I have made appropriate changes in the solve function-
solve(puzzleString) {
var board = this.boardParser(puzzleString)
var emptySpot = this.getDot(board);
var row = emptySpot[0];
var column = emptySpot[1];
// full board condition
if (this.solved(board)) {
return puzzleString;
}
for (var i = 1; i <= 9; i++) {
if (this.checkvalue(board, row, column, i)) {
board[row][column] = i;
var boardString = this.stringifyBoard(board);
var result = this.solve(boardString);
if(result !== false){
return result;
}
}
}
// if board is unsolvable return false
return false;
}
for (var i = 1; i <= 9; i++) {
if (this.checkvalue(board, row, column, i)) {
board[row][column] = i;
var boardString = this.stringifyBoard(board);
if(this.solve(boardString)) return true; //I've a modification here
}
}
You didn't write any code to stop the function when the solution is found.
Here is my solution:
for (var i = 1; i <= 9; i++) {
if (this.checkvalue(board, row, column, i)) {
board[row][column] = i;
var boardString = this.stringifyBoard(board);
var sol = this.solve(boardString); // change
if (sol) return sol // change
}
}
I have done a similar one in python a while ago.
Check it here if you are interested: https://onlinegdb.com/SJt2PQrjP

How can speed up search loop?

There is a cycle with the condition how can it be optimized so that the search is faster?
for (var i = 0; i < db.rows.length; i++) {
for (var j = 0; j < user.rows.length; j++) {
for (var k = 0; k < work.length; k++) {
if (db.rows[i].LOGIN === user.rows[j].login && work[k].name === db.rows[i].NAME) {
}
}
}
}
This is typically something that you would expect to see executed on the database.
That being said, you can split up the condition, so that you don't need to perform the second nested loop for every row:
for (var i = 0; i < db.rows.length; i++) {
for (var j = 0; j < user.rows.length; j++) {
if (db.rows[i].LOGIN === user.rows[j].login) {
for (var k = 0; k < work.length; k++) {
if (work[k].name === db.rows[i].NAME) {
}
}
}
}
}
You could take two Maps for the user logins and work names.
var userLogins = new Map(user.rows.map(o => [o.login, o])),
workNames = new Map(o => [o.name, o]),
for (var i = 0; i < db.rows.length; i++) {
if (userLogins.has(db.rows[i].LOGIN) && workNames.has(work[k].name)) {
// do something
}
}
If you need just the simple check with using the objects of user.rows or work, you could take a Set instead.
var userLogins = new Set(user.rows.map(({ login } => login)),
workNames = new Set(({ name }) => name),
for (var i = 0; i < db.rows.length; i++) {
if (userLogins.has(db.rows[i].LOGIN) && workNames.has(work[k].name)) {
// do something
}
}

Anagram with JavaScript

const myAnagram = (arr1, arr2) => {
let str1 = arr1;
let str2 = arr2;
let temp1 = [];
let temp2 = [];
let flag = 0;
if (str1.length !== str2.length) return "Not Anagram statement A";
for (var i = 0; i < str1.length - 1; i++) {
temp1[i] = str1[i];
}
for (var j = 0; j < str2.length - 1; j++) {
temp2[i] = str2[i];
}
temp1.sort();
temp2.sort();
for (var k = 0; k < str1.length - 1; k++) {
if (temp1[j] !== temp2[j]) return "Not Anagram statement C";
return "Anagram! statement D";
}
}
The problem you have is with the identifiers you have used in loops.
Have a look at the corrected code.
function myAnagram(arr1, arr2) {
var str1 = arr1;
var str2 = arr2;
var temp1 = [];
var temp2 = [];
var flag = 0;
if (str1.length !== str2.length) {
return "Not Anagram statement A";
} else {
for (var i = 0; i < str1.length; i++) {
temp1[i] = str1[i];
}
for (var j = 0; j < str2.length; j++) {
temp2[j] = str2[j];
}
temp1.sort();
temp2.sort();
for (var k = 0; k < str1.length; k++) {
if (temp1[k] !== temp2[k]) {
return "Not Anagram statement C";
} else {
return "Anagram! statement D";
}
}
}
}
Hope it helps !!
PS: You can optimize this code to a great extend.
find two strings are equal size
compare the characters and the count of characters matches
const isAnagram = (str1, str2) => {
const compare = (first, next) => {
return first.split('').sort().join('') === next.split('').sort().join('');
}
return str1.length !== str2.length ? false : compare(str1, str2);
}
Your loops always skip the last elements since you use < together with str1.length - 1. You should either use for (var i = 0; i < str1.length; ++i) {...} or for (var i = 0; i <= str.length-1; ++i) {...}
Furthermore in your comparison loop you already return when the first characters match (or when they don't). Therefore the loop will never compare the second (or nth) characters. The loop should further compare the characters until you are sure the arrays differ at some point.
You can shrink the function like
function isAnagram(str1, str2) {
if (str1.length !== str2.length) return false
var arr1 = arr2 = []
for (var i = 0; i < str1.length; ++i) {
arr1[i] = str1[i]
arr2[i] = str2[i]
}
arr1.sort()
arr2.sort()
for (var i = 0; i < arr1.length; ++i)
if (arr1[i] !== arr2[i]) return false
return true
}
And then
if (isAnagram("frog","rg0f")) {
console.log("Anagram!")
} else {
console.log("Not Anagram.")
}

How to make the function reusable in javascript

I have an array of objects and the property are id and name.
Now I have a function that checks the duplicate value of id and name.
My problem is I make the function redundant. I want to use the code only once to make it as reusable.
The only difference is the property name. Are there any solution to use the function only once? Thanks
var data = [{id: 0, name: "lina"}, {id: 1, name: "jona"}, {id: 2, name: "lina"}, {id: 0},{id: 3, name: "anna"}];
function isDuplicateID() {
for(var i = 0; i < data.length; i++) {
if(data[i].id === 0)
continue;
for(var j = i+1; j < data.length; j++) {
if(data[j].id === data[i].id)
return true;
}
}
return false;
}
function isDuplicateName() {
for(var i = 0; i < data.length; i++) {
if(data[i].name === 0)
continue;
for(var j = i+1; j < data.length; j++) {
if(data[j].name === data[i].name)
return true;
}
}
return false;
}
alert(isDuplicateID())
alert(isDuplicateName())
You can add parameter key and use it. Following code depicts the same
function isDuplicateID(key) {
for(var i = 0; i < data.length; i++) {
if(data[i][key] === 0)
continue;
for(var j = i+1; j < data.length; j++) {
if(data[j][key] === data[i][key])
return true;
}
}
return false;
}
Properties in javascript can be get by either using obj.propName or obj[propName].
var data = [{id: 0, name: "lina"}, {id: 1, name: "jona"}, {id: 2, name: "lina"}, {id: 0},{id: 3, name: "anna"}];
function isDuplicate(propName) {
for (var i = 0; i < data.length; i++) {
if (data[i][propName] === 0)
continue;
for (var j = i + 1; j < data.length; j++) {
if (data[j][propName] === data[i][propName])
return true;
}
}
return false;
}
alert(isDuplicate("id"))
alert(isDuplicate("name"))
Instead of using . to access properties you can enclosed the property name in square brackets, ie instead of . you can use [].
This means you can then pass in the property name, one of the great features of javascript.
function isDuplicate(propertyName) {
for(var i = 0; i < data.length; i++) {
if(data[i][propertyName] === 0)
continue;
for(var j = i+1; j < data.length; j++) {
if(data[j][propertyName] === data[i][propertyName])
return true;
}
}
return false;
}
pass a parameter to your function to choose between the properties:
function isDuplicate(field) {
for(var i = 0; i < data.length; i++) {
if(data[i][field] === 0)
continue;
for(var j = i+1; j < data.length; j++) {
if(data[j][field] === data[i][field])
return true;
}
}
return false;
}
alert(isDuplicate('id'))
alert(isDuplicate('name'))
I'd be inclined to rewrite that function so you only have one loop using indexOf to check for duplicates in a temporary array.
function hasDuplicate(type) {
for (var dupe = [], i = 0, l = data.length; i < l; i++) {
var val = data[i][type];
if (dupe.indexOf(val) > -1) return true;
if (val !== 0) dupe.push(val);
}
return false;
}
hasDuplicate('id');
DEMO

javascript matrix manipulation is not working

This is a bad coded solution to a problem in "advent of code": link to problem
I don't know the reason because my code is not working properly, I had an error related to regular expressions cause I didn't reset the pointer of the regexp object, now that error is fixed I think, but something is escaping to my knowledge in what I've done bad.
The problem is that the solution that my code displays is not correct, you can submit a solution on the link I've provided and get feedback of your solutions.
Correct solution: 543903
Given solution: 418954
// day 6 of advent of code
var input = "removed, take from problem";
function processInput(input, matrix) {
var linesOfInput = input.split("\n");
var matches;
var turnOnRE = /turn on (\d+),(\d+).*?(\d+),(\d+)/g;
var turnOffRE = /turn off (\d+),(\d+).*?(\d+),(\d+)/g;
var toggleRE = /toggle (\d+),(\d+).*?(\d+),(\d+)/g;
// regular expression objects lastIndex property must be 'reseted' in order to work well
for (var i = 0 ; i < linesOfInput.length; i++) {
turnOnRE.lastIndex = 0;
turnOffRE.lastIndex = 0;
toggleRE.lastIndex = 0;
matches = turnOnRE.exec(linesOfInput[i]);
if (matches != null) {
manipulateLights(matrix, matches[1], matches[2], matches[3], matches[4], true);
continue;
}
matches = turnOffRE.exec(linesOfInput[i]);
if (matches != null) {
manipulateLights(matrix, matches[1], matches[2], matches[3], matches[4], false);
continue;
}
matches = toggleRE.exec(linesOfInput[i]);
manipulateLights(matrix, matches[1], matches[2], matches[3], matches[4]);
}
}
function manipulateLights(matrix, startI, startJ, endI, endJ, newValue) {
if (newValue == undefined) { // toogle
for (var i = startI ; i <= endI; i++) {
for (var j = startJ ; j <= endJ; j++) {
matrix[i][j] = !matrix[i][j];
}
}
console.log(startI, startJ, endI, endJ, newValue);
} else {
for (var i = startI ; i <= endI; i++) {
for (var j = startJ ; j <= endJ; j++) {
matrix[i][j] = newValue;
}
}
console.log(startI, startJ, endI, endJ, newValue);
}
console.log(countTurnedOnLights(matrix));
}
function countTurnedOnLights(matrix) {
var turnedOn = 0;
for (var i = 0 ; i < matrixWidth; i++) {
for (var j = 0 ; j < matrixHeigth; j++) {
if (matrix[i][j] == true) {
turnedOn++;
}
}
}
return turnedOn;
}
var matrixHeigth = 1000;
var matrixWidth = 1000;
// define a bidimensional array, is almost like in C++
var lightMatrix = new Array(matrixWidth);
for (var i = 0 ; i < matrixWidth; i++) {
lightMatrix[i] = new Array(matrixHeigth);
}
// turn off all lights
for (var i = 0 ; i < matrixWidth; i++) {
for (var j = 0 ; j < matrixHeigth; j++) {
lightMatrix[i][j] = false;
}
}
processInput(input, lightMatrix);
console.log(countTurnedOnLights(lightMatrix));
OK I figured out the error - your regular expression matches are being treated as strings when you first create your for loops.
for (var i = startI ; i <= endI; i++) {
for (var j = startJ ; j <= endJ; j++) {
When you hit a combo like 756,53 through 923,339, it thinks 53 > 339 and it exits the loop immediately. Either wrap each "start" variable with Number() in your for loops, or do so when passing the parameters.

Categories

Resources