Javascript reverse sorting - javascript

i have a problem on javascript reverse method when all the data to be sorted are equal.
here is my code:
var ascAgt = false;
function sortTableAgt() {
var tbl = document.getElementById("mytable").tBodies[0];
var store = [];
for (var i = 0, len = tbl.rows.length; i < len; i++) {
var row = tbl.rows[i];
var rowdatedata = row.cells[1].innerHTML;
store.push([rowdatedata, row]);
}
if (ascAgt) {
store.sort();
ascAgt = false;
} else {
store.sort();
store.reverse();
ascAgt = true;
}
for (var i = 0, len = store.length; i < len; i++) {
var idno = i + 1;
store[i][1].cells[0].innerHTML = idno.toString();
tbl.appendChild(store[i][1]);
} store = null;
}
sample data:
ID Name Date
1 XXXXX 2012/10/05
2 XXXXX 2012/03/16
3 XXXXX 2012/05/18
4 XXXXX 2012/05/18
as i sort the name part,what i want is that nothing happens because names are equal but when it comes to the reverse method it will just reversed the given data.
am i missing something here?
thank you in advance....

So, what you want is to sort by 2nd column and, if the values are equal, sort also by 3rd column. Right?
The sort() function takes also a callback. You have to use that.
var ascAgt = false;
function sortTableAgt() {
var table = document.getElementById("mytable").tBodies[0],
rows = table.rows,
len = rows.length,
i = 0,
store = [],
order = ascAgt ? 1 : -1;
for (i = 0; i < len; i++) {
store.push(rows[i]);
}
store.sort(function(a, b) {
if (a.cells[1].innerHTML == b.cells[1].innerHTML) {
// If 2nd cell are equal, sort by 3rd cell
// Compare them as date (timestamp)
var dateA = new Date(a.cells[2].innerHTML).getTime(),
dateB = new Date(b.cells[2].innerHTML).getTime();
if (dateA == dateB) {
return 0;
} else if (dateA < dateB) {
return -1 * order;
} else {
return 1 * order;
}
} else if (a.cells[1].innerHTML < b.cells[1].innerHTML) {
return -1 * order;
} else {
return 1 * order;
}
});
for (i = 0; i < len; i++) {
store[i].cells[0].innerHTML = (i+1).toString();
table.appendChild(store[i]);
}
}
You can also check tis demo in JSBin: http://jsbin.com/welcome/39336/edit

Related

Find longest sequence of zeros in binary representation of an integer in JavaScript?

Well in this question I have to find the longest sequence of zeros in the binary representation of an integer.
After a lot of hard work, I'm able to find the longest sequence of zeros with my logic which I changed many times.
I have one problem with my logic which is if I input an integer that has no gap in it has to give me an answer 0 which I tried to make by myself but I failed.
Right now if I input an integer that has no gap it gives me output infinity.
I want my answer to print 0 when the binary representation of an integer has no gap in it.
var dn = prompt("Enter a number: ");
var bn = new Array();
var i = 0;
var binary = [];
while (dn != 0) {
bn[i] = dn % 2;
dn = Math.floor(dn / 2);
i++;
}
for (var j = i - 1; j >= 0; j--) {
binary.push(bn[j]);
}
console.log(binary.join(""));
var currentGap = 0;
var gaps = [];
var len = binary.length;
for (var k = 0; k < len; k++) {
if (binary[k] == 0) {
currentGap++;
if (binary[k + 1] == 1) {
gaps.push(currentGap);
currentGap = 0;
}
}
}
console.log(Math.max(...gaps));
You could add initialize gaps with 0, or add condition when gaps remains empty to print 0 else max of gaps.
var dn = prompt("Enter a number: ");
var bn = new Array();
var i = 0;
var binary = [];
while (dn != 0) {
bn[i] = dn % 2;
dn = Math.floor(dn / 2);
i++;
}
for (var j = i - 1; j >= 0; j--) {
binary.push(bn[j]);
}
console.log(binary.join(""));
var currentGap = 0;
//var gaps = []
var gaps = [0];
var len = binary.length;
for (var k = 0; k < len; k++) {
if (binary[k] == 0) {
currentGap++;
if (binary[k + 1] == 1) {
gaps.push(currentGap);
currentGap = 0;
}
}
}
//if (gaps.length === 0)
// console.log(0)
//else
// console.log(Math.max(...gaps));
console.log(Math.max(...gaps));
You can simply print 0 if your gaps array has no length.
var dn = prompt("Enter a number: ");
var bn = new Array();
var i = 0;
var binary = [];
while (dn != 0) {
bn[i] = dn % 2;
dn = Math.floor(dn / 2);
i++;
}
for (var j = i - 1; j >= 0; j--) {
binary.push(bn[j]);
}
console.log(binary.join(""));
var currentGap = 0;
var gaps = [];
var len = binary.length;
for (var k = 0; k < len; k++) {
if (binary[k] == 0) {
currentGap++;
if (binary[k + 1] == 1) {
gaps.push(currentGap);
currentGap = 0;
}
}
}
console.log(gaps.length ? Math.max(...gaps) : 0); // <-- This
I apologize if I'm misunderstanding your question, but would this satisfy your problem?
const s = prompt("Enter a number:");
const longest = Math.max(...parseInt(s).toString(2).split('1').map(s=>s.length));
console.log(longest);
just change var gaps = [];
to var gaps = [0];
You can also do that...
let dn = parseInt(prompt("Enter a number: "))
if (isNaN(dn)) console.log('Not a Number!')
else
{
let
dnStr = dn.toString(2) // binary convertion
, count = 0
, zVal = '0'
;
while (dnStr.includes(zVal) )
{
count++
zVal += '0'
}
console.log( `${dnStr}\n--> ${count}` )
}
If you want to do your own binary convertion, prefert o use Javasscript binary opérators:
let dn = parseInt(prompt("Enter a number: "))
if (isNaN(dn)) console.log('Not a Number!')
else
{
let gap = [0]
let Bin = []
let count = 0
for (;;)
{
Bin.unshift( dn & 1 ) // --> dn % 2
if (dn & 1)
{
gap.push(count)
count = 0
}
else count++
dn >>>=1 // --> dn = Math.floor(dn / 2)
if (!dn) break // --> if (dn === 0 )
}
console.log(Bin.join(''))
console.log(Math.max(...gap))
}
I had a go at this and this is what I came up with as a function:
function binaryGap(N){
let binary = Math.abs(N).toString(2); // Convert to Binary string
let binarySplit = binary.split("1"); // Split the string wherever there is "1"
let tempBinaryArr = []; // create an empty array to store the element from Splice
let max = 0; // Setting the max length to zero to compare with each element
// Removing the zeros at the end
if(binarySplit[binarySplit.length -1] == 0){
tempBinaryArr = binarySplit.splice(binarySplit.length -1, 1);
}
//Looping through each element of binarySplit to compare with variable max
for(let j=0; j < binarySplit.length; j++){
if(max < binarySplit[j].length){
max = binarySplit[j].length;
}
}
return `Longest Sequence of Zeros: ${max}`;
}
If I understood the task correctly, you can arrange the logic in something like this. In case if the input comes as a string you don't need the .toString() part
function splitByZero(str) {
const eachSubstr = str
.toString()
.split(1)
.filter((e) => e); //to remove empty values in the new array
let maxLength = 0;
for (const substr of eachSubstr) {
if (maxLength < substr.length) {
maxLength = substr.length;
}
}
console.log(maxLength);
}
splitByZero(111011100011);
function findLongestDistance(){
findGap("1000100100001");
findGap("1000100");
findGap("000100");
findGap("10000");
findGap("000001");
findGap("111111")
}
function findGap(n){
var split = n.split(/1/g);
var longestZeros = 0;
if(split.length>2){
for(var i in split){
var len = split[i].length;
if(len>longestZeros){
longestZeros = len;
}
}
console.log(longestZeros);
return longestZeros;
}
console.log(0);
return 0;
}

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 to get common substring in two string to maintain order?

I am trying to do one problem of hackerrank but I am not able to solve that problem
Can someone please help me with wrong logic implementation done by me?
problem
Print the length of the longest string, such that is a child of both s1 and s2.
Sample Input
HARRY
SALLY
Sample Output
2
Explanation
The longest string that can be formed by deleting zero or more characters from HARRY and SALLY is AY, whose length is 2.
Sample Input 1
AA
BB
Sample Output 1
0
Explanation 1
AA and BB have no characters in common and hence the output is 0
Sample Input 2
SHINCHAN
NOHARAAA
Sample Output 2
3
Explanation 2
The longest string that can be formed between SHINCHAN and NOHARAAA while maintaining the order is NHA.
I have written some logic which is as follows:
function commonChild(s1, s2) {
var arr = s2.split(),
currenString = '',
maxLength = 0,
index = -1;
console.log(arr);
for (var i = 0; i < s1.length; i++) {
var char = s1.charAt(i),
charIndex = arr.indexOf(char);
console.log(char)
if (index < charIndex) {
index = charIndex;
currenString +=char;
}
maxLength= Math.max(maxLength,currenString.length)
}
return maxLength;
}
commonChild('ABCDEF', 'FBDAMN');
console.log(commonChild('ABCDEF', 'FBDAMN'));
pardon me. this is an unoptimized solution.
function maxCommon(a, b, offset) {
offset = offset || 0;
if (a === b) {
return [[a, b]];
}
var possibleSolns = [];
for (var i = 0 + offset; i < a.length; i++) {
for (var j = 0 + offset; j < b.length; j++) {
if (a.charAt(i) === b.charAt(j)) {
possibleSolns.push([
a.substring(0, offset) + a.substring(i),
b.substring(0, offset) +b.substring(j)
]);
break;
}
}
}
var results = [];
possibleSolns.forEach(function(soln) {
var s = maxCommon(soln[0], soln[1], offset+1);
if (s.length === 0) {
s = [[soln[0].substring(0, offset +1), soln[1].substring(0, offset +1)]];
}
results = results.concat(s);
});
return results;
}
var maxLen = -1;
var soln = null;
maxCommon("ABCDEF", "FBDAMN").map(function(_) {
return _[0];
}).forEach(function(_) {
if (_.length > maxLen) {
soln = _;
maxLen = _.length;
}
});
console.log(soln);
I kept most of your logic in the answer:
function commonChild(s1, s2) {
var // Sets strings to arrays
arrayString1 = s1.split(""),
arrayString2 = s2.split(""),
collectedChars = "",
maxLength = 0,
max = arrayString1.length;
for (var i = 0; i < max; i++) {
var
char = arrayString1[i],
count = arrayString2.indexOf(char);
// check if char is in second string and not in collected
if (count != -1 && collectedChars.indexOf(char) == -1) {
collectedChars += char;
maxLength++;
}
}
return maxLength;
}
// expected output 4
console.log(commonChild(
'ABCDEF',
'FBDAMN'
));
// expected output 1
console.log(commonChild(
'AA',
'FBDAMN'
));
Using lodash and spread operation you can do it in this way.
const test = (first, second) => {
const stringArray1 = [...first];
const stringArray2 = [...second];
return _.intersection(stringArray1, stringArray2).length;
}
console.log(test('ABCDEF', 'FBDAMN'));
You can solve it using lcs least common subsequence
function LCS(s1,s2,x,y){
var result = 0;
if(x==0 || y==0){
result = 0
}else if(s1[x-1] == s2[y-1]){
result = 1+ LCS(s1,s2,x-1,y-1)
} else if(s1[x-1] != s2[y-1]){
result = Math.max(LCS(s1,s2,x-1,y), LCS(s1,s2,x,y-1))
}
return result;
}
// Complete the commonChild function below.
function commonChild(s1, s2) {
return LCS(s1,s2,s1.length,s2.length);
}
Based on your code before the edit.
One little change is to change var arr = s2.split() to split('').
The main change in the logic is that I added a loop to run over the string each time from another character (first loop from the first, second from the second etc).
function commonChild(s1, s2) {
var arr = s2.split(''),
currenString = '',
maxLength = 0,
index = -1,
j = -1;
for (var ii = 0; ii < s1.length; ii++) {
index = -1;
currenString = '';
for (var i = ii; i < s1.length; i++) {
var char = s1.charAt(i),
j = arr.indexOf(char);
if (index < j) {
index = j;
currenString += char;
}
maxLength = Math.max(maxLength, currenString.length)
}
}
return maxLength;
}
console.log(commonChild('ABCDEF', 'FBDAMN'));

javascript array - increment value at given key

I have a dynamic array and I am trying to increment the value by 1 if the key exists in the array. According to my debug it is incrementing the key and and creating a second key/value pair.
A snippet of my code:
for (var i = 0; i < choices.length; i++) {
console.log(choices[i]);
if (choices[i].YearTermId == 1) {
if (!lookup(firstChoice, choices[i].FirstChoiceOptionId)) {
firstChoice.push({
key: choices[i].FirstChoiceOptionId,
value: 1
});
} else {
firstChoice[choices[i].FirstChoiceOptionId] = firstChoice[choices[i].FirstChoiceOptionId] + 1;
}
more if/else..
function lookup( arr, name ) {
for(var i = 0, len = arr.length; i < len; i++) {
if( arr[ i ].key === name )
return true;
}
return false;
}
You're using an array where you should be using an object. If you use an object, your code can be rewritten as:
var firstChoice = {};
for (var i = 0; i < choices.length; i++) {
var firstChoiceOptionId = choices[i].FirstChoiceOptionId;
if (choices[i].YearTermId == 1) {
firstChoice[firstChoiceOptionId] = firstChoice[firstChoiceOptionId]
? firstChoice[firstChoiceOptionId] + 1
: 1;
/* ... */
}
}
If you need the data as an array afterwards, just map it:
var firstChoiceArray = Object.keys(firstChoice).map(function(key) {
return {
key: key,
value: firstChoice[key]
};
});
Conversely, if you have an input array and want to convert it to an object for manipulation, reduce it:
var firstChoice = firstChoiceArray.reduce(function(result, current) {
result[current.key] = current.value;
return result;
}, {});
I think you should increment value key, like:
firstChoice[choices[i].FirstChoiceOptionId].value ++;
And I would like to rewrite this code to:
var firstChoice = {};
for (var i = 0; i < choices.length; i++) {
if (choices[i].YearTermId == 1) {
if (!firstChoice[choices[i].FirstChoiceOptionId]) {
firstChoice[choices[i].FirstChoiceOptionId] = 0;
}
firstChoice[choices[i].FirstChoiceOptionId]++;
}
}
console.log(firstChoice);
Try with Array.map:
Example:
var a = [{key:"ab","value":1},{key:"cd","value":1},{key:"ef","value":1}];
a.map(function(item){if(item.key == this){item.value++}}, "cd");
So, a[1] will have value 2 after that.

Using Javascript find array values in another array and in order

Here is one to get your brain going! I've not had any luck with it.
[1,2,1,1,2,1,1,1,2,2]
[1,2,1,1,2,1]
I would like to use the second array to find the values in the first, but they must be in the same order.
Once for I would like it to return the next key up from the last key in the second array.
So in this example it would use the first six digits in the first array and then return 6 as the key after the final one in the second array.
var a2 = [1,2,1,1,2,1,1,1,2,2]
var a1 = [1,2,1,1,0,1]
function find(arr1, arr2) {
var len = 1
var result = 0;
var s2 = arr2.toString();
for (len=1;len <= a1.length; len++)
{
var aa1 = arr1.slice(0, len)
var s1 = aa1.toString();
if(s2.indexOf(s1)>=0){
result = aa1.length;
}
else {
break;
}
}
return result;
}
alert(find(a1, a2));
var find = function(haystack, needle) {
var doesMatch = function(offset) {
for (var i = 0; i < needle.length; i++) {
if (haystack[i+offset] !== needle[i]) {
return false;
}
}
return true;
};
for (var j=0; j < haystack.length - needle.length; j++) {
if (doesMatch(j)) {
return j;
}
}
return -1;
};
This is quick, this is dirty, and this is correct only if your data doesn't include any comma.
var needle = [1,2,1,1,2,1];
var haystack = [1,2,1,1,2,1,1,1,2,2];
if ( needle.length <= 0 ) return 0;
var fromStr = ','+haystack.toString()+','
var findStr = ','+needle.toString()+','
// Find ',1,2,1,1,2,1,' in ',1,2,1,1,2,1,1,1,2,2,'
var pos = fromStr.indexOf(findStr);
// Count the end position requested
return pos >= 0 ? fromStr.slice(0,pos+1).match(/,/g).length + needle.length - 1 : -1;
Note: The comma at head and tail is to make sure [22,12] doesn't match [2,1].

Categories

Resources