How to "update" a variable? - javascript

I have this:
let points = something
let obj1 = {
points: points
}
The points value changes
let obj2 = {
points: points
}
I want that obj1.points is equal to the first points value and obj2.points the second. Here's more of the code:
constructor($){
let stats = $(".player-stats-info").get(0);
let points = parseInt(stats.children[5]) || 0;
this.rush = {
points: points
}
stats = $(".player-stats-info").get(1);
this.hikaBrain = {
points: points
}
stats = $(".player-stats-info").get(2);
this.skyWars = {
points: points
}
stats = $(".player-stats-info").get(3);
this.octogone = {
points: points
}
//etc
}

It sounds like you want a function that returns an object with the right structure:
const makeObj = stats => ({
points: parseInt(Object.byString(stats.children[5], d)) || 0,
gameCount: parseInt(Object.byString(stats.children[7], d)) || 0,
victoryCount: parseInt(Object.byString(stats.children[9], d)) || 0,
defeatCount: parseInt(Object.byString(stats.children[11], d)) || 0,
gameTime: ms(Object.byString(stats.children[13], d)) || 0,
killCount: parseInt(Object.byString(stats.children[15], d)) || 0,
deathCount: parseInt(Object.byString(stats.children[17], d)) || 0,
});
Then just call makeObj with the stats:
this.rush = makeObj($(".player-stats-info").get(0));
this.skyWars = makeObj($(".player-stats-info").get(1));
// etc

Related

Several JavaScript Objects are absolutely identical

steps["main_algorithm"] is filled with objects of the main_algorithm_structure.
main_algorithm_structure["loop1"] is filled with objects of the loop1_struct.
(The struct or structure objects are always copied with Object.create() or Object.assign({}, 'structure_name'))
The Problem is different objects of main_algorithm_structure, that means at the end different objects of steps["main_algorithm"] have the exact same loop1 object. I am trying to solve that problem for days now.. i am very desperate and this bug needs to be fixed...
Look at the Java Script Logic below those objects.
let steps = {
"str_to_hash" : "",
"init_constants" : [],
"input_to_bit_translation" : [],
"input_length_preprocessing" : [],
"final_input_preprocessing" : [],
"final_input_preprocessing_result" : [],
"main_algorithm" : [],
"hash_digest" : "",
}
let main_algorithm_structure = {
chunk_number : undefined,
chunk_preprocessed : undefined,
loop1 : [],
preConstants : undefined,
loop2 : [],
old_constants : undefined,
new_constants : undefined
}
let loop1_struct = {
lp1_sh1 : undefined,
lp1_sh2 : undefined,
lp1_add1 : undefined,
lp1_add2 : undefined,
lp1_s0 : undefined,
lp1_s1 : undefined,
lp1_y : undefined,
lp1_w : []
}
In the last if(crSteps) - Block, a copy of the loop1_structure is filled with data. This loop1_structure is pushed to main_algorithm_structure["loop1"]. Later in the algorithm this main_algorithm structure is further filled with data and at the end pushed to steps["main_algorithm"]. At the end of the whole script, the structure steps is returned by the function.
In every object of steps["main_algorithm"] the loop1-array is exactly the same. Why?
I hope the for-loop is everything which is needed to find the bug:
for(let x = 0; x<chunks.length; x++) {
if(crSteps) {structCopy = Object.assign({}, main_algorithm_structure)}
if(crSteps) {structCopy.chunk_number = x}
//chunking every 512 bit chunk into 32 bit chunks -> w's result is 16 32 bit chunks
let w = chunker(chunks[x], 32)
//adding 48 32 bit chunks (every chunk is full of zeros)
for(let m = 0; m != 48; m++) {
w.push([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
}
if(crSteps) {
let toPush = []
for(let c = 0; c<w.length; c++) {
let temp = ""
for(let c_ = 0; c_<w[c].length; c_++) {
temp += String(w[c][c_])
}
toPush.push(temp)
}
structCopy["chunk_preprocessed"] = toPush.slice()
}
for(let y = 16; y<64; y++) {
const sh1 = y-15
const sh2 = y-2
const add1 = y-16
const add2 = y-7
const s0 = XORXOR(rotr(w[sh1].slice(), 7), rotr(w[sh1].slice(), 18), shr(w[sh1].slice(), 3))
const s1 = XORXOR(rotr(w[sh2].slice(), 17), rotr(w[sh2].slice(), 19), shr(w[sh2].slice(), 10))
w[y] = add(add(add(w[add1].slice(), s0), w[add2].slice()), s1)
if(crSteps) {
let copy_loop1_struct = Object.create(loop1_struct)
copy_loop1_struct.lp1_sh1 = sh1
copy_loop1_struct.lp1_sh2 = sh2
copy_loop1_struct.lp1_add1 = add1
copy_loop1_struct.lp1_add2 = add2
copy_loop1_struct.lp1_s0 = s0.slice()
copy_loop1_struct.lp1_s1 = s1.slice()
copy_loop1_struct.lp1_y = y
let toPush= []
for(let c = 0; c<w.length; c++) {
toPush.push(w[c].slice().join(""))
}
copy_loop1_struct.lp1_w = toPush.slice()
structCopy.loop1.push(copy_loop1_struct)
}
}

Algorithm - River Sizes - Code works but prompt complains memory leak

Can people help to point out the problem with the code below? By inspecting the console.log, the code is working as intended, however, the prompt complains "Oops, your code timed out or ran out of memory. Check for infinite loops or memory leaks."
The code is not stuck in an infinite loop, so it must be about memory leaks. What is a memory leak, what is the problems with the code? Appreciated!
function riverSizes(matrix) {
let isVisitedMatrix = Array(matrix.length).fill(false).map(ele => Array(matrix[0].length).fill(false));
let lengthMatrix = [];
for (let row=0; row<matrix.length; row++)
{
for (let col=0; col<matrix[0].length; col++)
{
if (isVisitedMatrix[row][col] === true) continue;
isVisitedMatrix[row][col] = true;
if (matrix[row][col]===1)
{
const startNode = new Node(row, col);
const length = traverseNeighbour(matrix, [startNode], 1, isVisitedMatrix);
lengthMatrix.push(length);
}
}
}
return lengthMatrix; }
function traverseNeighbour(matrix, queue, currLength, isVisitedMatrix)
{
if (queue.length === 0) return currLength;
const startNode = queue.shift();
const row = startNode.row;
const col = startNode.col;
isVisitedMatrix[row][col] = true;
if (row-1>=0 && matrix[row-1][col]===1 && isVisitedMatrix[row-1][col]===false)
{
currLength += 1;
const top = new Node(row-1, col);
queue.push(top);
}
if (row+1<matrix.length && matrix[row+1][col]===1 && isVisitedMatrix[row+1][col]===false)
{
currLength += 1;
const bottom = new Node(row+1, col);
queue.push(bottom);
}
if (col-1>=0 && matrix[row][col-1]===1 && isVisitedMatrix[row][col-1]===false)
{
currLength += 1;
const left = new Node(row, col-1);
queue.push(left);
}
if (col+1 < matrix[0].length && matrix[row][col+1]===1 && isVisitedMatrix[row][col+1]===false)
{
currLength += 1;
const right = new Node(row, col+1);
queue.push(right);
}
return traverseNeighbour(matrix, queue, currLength, isVisitedMatrix);
}
class Node {
constructor(_row, _col)
{
this.row = _row;
this.col = _col;
}
}
Here is the question.
You're given a two-dimensional array (a matrix) of potentially unequal height and width containing only 0s and 1s. Each 0 represents land, and each 1 represents part of a river. A river consists of any number of 1s that
are either horizontally or vertically adjacent (but not diagonally adjacent). The number of adjacent 1 s forming a river determine its size.
Note that a river can twist. In other words, it doesn't have to be a straight vertical line or a straight horizontal line; it can be L-shaped, for example.
Write a function that returns an array of the sizes of all rivers represented in the input matrix. The sizes don't need
to be in any particular order.
Sample Input
matrix = [
[1, 0, 0, 1, 0],
[1, 0, 1, 0, 0],
[0, 0, 1, 0 ,1],
[1, 0, 1, 0, 1],
[1, 0, 1, 1, 0],
]
Sample Output
[1, 2, 2, 2, 5] // The numbers could be ordered differently.
// The rivers can be clearly seen here:
// [
// [1, , , 1, ],
// [1, , 1, , ],
// [, , 1, , 1],
// [1, , 1, , 1],
// [1, , 1, 1, ],
// ]
Try marking the visited right before adding the node to the queue so that you can ensure that you only add a node to the queue once. Right now, you mark the nodes once they dequeue, so your queue is probably getting extremely big.
By the way, this whole "traverse a 2d array" stuff comes up a lot, so it's best to just memorize a simple dfs implementation like this:
const getRiverCount = map => {
const sizes = [];
const h = map.length;
const w = map[0].length
const dfs = (r, c) => {
if (r < 0 || c < 0 || r >= h || c >= w || map[r][c] === 0) return 0;
map[r][c] = 0;
return dfs(r + 1, c) + dfs(r - 1, c) + dfs(r, c + 1) + dfs(r, c - 1) + 1;
}
for (let r = 0; r < h; r++) {
for (let c = 0; c < w; c++) {
if (map[r][c] === 1) sizes.push(dfs(r, c));
}
}
return sizes;
}
Actually, the code isn't error-free (previously it repetitively adds nodes already in the queue to the queue again if that node is also neighbour with new nodes). After I edited the code, it passed all the tests :)
function riverSizes(matrix) {
const isVisitedMatrix = Array(matrix.length).fill(false).map(ele => Array(matrix[0].length).fill(false));
let lengthMatrix = [];
for (let row=0; row<matrix.length; row++)
{
for (let col=0; col<matrix[0].length; col++)
{
if (isVisitedMatrix[row][col] === true) continue;
isVisitedMatrix[row][col] = true;
if (matrix[row][col]===1)
{
const startNode = new Node(row, col);
const length = traverseNeighbour(matrix, [startNode], 0, isVisitedMatrix);
lengthMatrix.push(length);
}
}
}
return lengthMatrix;}
function traverseNeighbour(matrix, queue, currLength, isVisitedMatrix)
{
if (queue.length === 0) return currLength;
const startNode = queue.shift();
currLength += 1;
const row = startNode.row;
const col = startNode.col;
isVisitedMatrix[row][col] = true;
if (row-1>=0 && matrix[row-1][col]===1 && isVisitedMatrix[row-1][col]===false)
{
const top = new Node(row-1, col);
isVisitedMatrix[row-1][col] = true;
queue.push(top);
}
if (row+1<matrix.length && matrix[row+1][col]===1 && isVisitedMatrix[row+1][col]===false)
{
const bottom = new Node(row+1, col);
isVisitedMatrix[row+1][col] = true;
queue.push(bottom);
}
if (col-1>=0 && matrix[row][col-1]===1 && isVisitedMatrix[row][col-1]===false)
{
const left = new Node(row, col-1);
isVisitedMatrix[row][col-1] = true;
queue.push(left);
}
if (col+1 < matrix[0].length && matrix[row][col+1]===1 && isVisitedMatrix[row][col+1]===false)
{
const right = new Node(row, col+1);
isVisitedMatrix[row][col+1] = true;
queue.push(right);
}
return traverseNeighbour(matrix, queue, currLength, isVisitedMatrix);}
class Node {
constructor(_row, _col)
{
this.row = _row;
this.col = _col;
}
}

Get values according function parameters in Javascript

I have the next function:
const fun = (nr, car, color, obj) => {
const cars = nr - 2;
const colors = nr - 1;
const objects = nr -3;
const main = {
c: `${cars}cars.`,
co: `${colors}colors.`,
obj: `${objects}objects.`
};
console.log(car && main.c, color && main.co, obj && main.obj)
return `${car && main.c || color && main.co|| obj && main.obj}`;
};
console.log(fun(65, false, true, true))
How you can notice, depending by the parameters fun(65, false, true, true) i should get the correct data. In this example i should get this string 64colors. 62obj., but i don't get this. So depending by the parameters i want to show the corresponding values. How to do this?
Since you are using the or operator within the string, it just returns the result till a first non falsy value and not any further. You need to split your logic into three parts to be able to create a proper string
const fun = (nr, car, color, obj) => {
const cars = nr - 2;
const colors = nr - 1;
const objects = nr -3;
const main = {
c: `${cars}cars.`,
co: `${colors}colors.`,
obj: `${objects}objects.`
};
console.log(car && main.c, color && main.co, obj && main.obj)
return `${car && main.c || ''}${color && main.co || ''}${obj && main.obj || ''}`;
};
console.log(fun(65, false, true, true))
main.colors would return undefined which is falsy because it doesn't exist in the main object.
And the OR || operator doesn't return more than one value.
I changed the return statement so you can get 64colors62objects
const fun = (nr, car, color, obj) => {
const cars = nr - 2;
const colors = nr - 1;
const objects = nr -3;
const main = {
c: `${cars}cars.`,
co: `${colors}colors.`,
obj: `${objects}objects.`
};
return `${car && main.c ? main.c : ''}${color && main.co ? main.co : ''}${obj && main.obj ? main.obj : ''}`;
};
console.log(fun(65, false, true, true))

How to understand returning values from recursive function calls?

I am trying to recursively solve a maze using Javascript, how do I return my solution from my recursive function call?
I am attempting to create a maze solver algorithm using recursion, in Javascript. My maze shall follow the following pattern:
let rawMaze =
[
[0, 1, 3],
[0, 1, 0],
[2, 1, 0]
],
Where
0: wall
1: valid path
2: start
3: end
I create an object from the source array,
let maze = []
constructMaze() {
for (let i = 0; i < 3; i++) {
maze[i] = [];
for (let j = 0; j < 3; j++) {
const Cell = {
x: j,
y: i,
state: rawMaze[i][j],
id: uniqueId()
};
this.maze[i].push(Cell);
}
}
console.table(this.maze);
}
I also use a helper function to get the neighbours of any given cell,
getNeighbours(x, y) {
let maze = this.maze;
let neighbours = [];
maze.forEach(row => {
row.forEach(cell => {
if (
(cell.x == x && cell.y == y + 1) ||
(cell.x == x && cell.y == y - 1) ||
(cell.y == y && cell.x == x + 1) ||
(cell.y == y && cell.x == x - 1)
) {
neighbours.push(cell);
}
});
});
return neighbours;
}
The main logic happens in my checkNeighbours function, where I determine the next possible moves and follow them up,
checkNeighbours(neighbours, path, visited) {
let validMoves = [];
neighbours.forEach(potentialMove => {
if (visited.indexOf(potentialMove.id) < 0) {
if (potentialMove.state !== 0) {
validMoves.push(potentialMove);
}
}
});
if (validMoves.length === 0) {
return;
} else {
let finish = validMoves.filter(cell => cell.state === 3);
console.log(finish);
if (finish.length === 1) {
return path;
}
}
validMoves.forEach(validMove => {
path.push(validMove);
visited.push(validMove.id);
this.checkNeighbours(
this.getNeighbours(validMove.x, validMove.y),
path,
visited
);
});
}
I then proceed to try and put this all together and solve the maze,
initSolve(maze) {
let maze = maze;
let start = [];
let paths = [];
let visited = [];
let current = null;
maze.forEach(row => {
row.forEach(cell => {
// Is start?
if ((start.length == 0) & (cell.state == 2)) {
start.push(cell);
visited.push(cell.id);
current = cell;
}
});
});
let result = this.checkNeighbours(
this.getNeighbours(current.x, current.y),
paths,
visited
);
console.log("test", result);
}
My question is the following. Using this very contrived and simple maze configuration, I have stepped through the code and can confirm that my
checkNeighbours()
function will recursively arrive at the end. At that point, the function has an array (the variable path) that contains the correct steps through the maze. How do I return this branch, if you will, from the recursive call? What happens when there are multiple branches?
The only thing I can think of is using a global variable, but I feel this can not be correct.
This is ripped from a React frontend , here is runnable code:
let rawMaze = [
[0, 1, 3],
[0, 1, 0],
[2, 1, 0]
]
let maze = []
function constructMaze() {
let counter = 0
for (let i = 0; i < 3; i++) {
maze[i] = [];
for (let j = 0; j < 3; j++) {
const Cell = {
x: j,
y: i,
state: rawMaze[i][j],
id: counter
};
maze[i].push(Cell);
counter++
}
}
}
function getNeighbours(x, y) {
let maze = this.maze;
let neighbours = [];
maze.forEach(row => {
row.forEach(cell => {
if (
(cell.x == x && cell.y == y + 1) ||
(cell.x == x && cell.y == y - 1) ||
(cell.y == y && cell.x == x + 1) ||
(cell.y == y && cell.x == x - 1)
) {
neighbours.push(cell);
}
});
});
return neighbours;
}
function checkNeighbours(neighbours, path, visited) {
let validMoves = [];
neighbours.forEach(potentialMove => {
if (visited.indexOf(potentialMove.id) < 0) {
if (potentialMove.state !== 0) {
validMoves.push(potentialMove);
}
}
});
if (validMoves.length === 0) {
return;
} else {
let finish = validMoves.filter(cell => cell.state === 3);
console.log(finish);
if (finish.length === 1) {
return path;
}
}
validMoves.forEach(validMove => {
path.push(validMove);
visited.push(validMove.id);
this.checkNeighbours(
this.getNeighbours(validMove.x, validMove.y),
path,
visited
);
});
}
function initSolve() {
let maze = constructMaze()
let start = [];
let paths = [];
let visited = [];
let current = null;
maze.forEach(row => {
row.forEach(cell => {
// Is start?
if ((start.length == 0) & (cell.state == 2)) {
start.push(cell);
visited.push(cell.id);
current = cell;
}
});
});
let result = this.checkNeighbours(
this.getNeighbours(current.x, current.y),
paths,
visited
);
console.log("test", result);
}
Might I recommend adding another class:
function Path() {
this.isValidPath = false;
this.pathArray = [];
}
And also reworking the checkNeighbours function to rename/include these parameters?
checkNeighbours(neighbours, paths, currentPathIndex, visited)
This way, paths could contain an array of Path classes, and you could set the isValidPath flag to true when you found a valid path (assuming you want to also include invalid and valid paths in the array). This would allow you to return all paths (branches). Each branch would be in the paths array at position currentPathIndex, which you'd increment in the code once one path is complete and you want to start searching for another path.
Also, currently the checkNeighbours function appears to do a breadth first search for valid moves. Perhaps if you reworked it into more of a depth-first traversal, then you could add each valid path (and exclude any invalid paths) to the paths array you return.

Javascript update a dictionary according to list index

I have a list which contains a team according to color:
var team = ["Red","Green","Blue","Yellow","Black","White","Orange"]
var from = 0
var to = 5
team.splice(to, 0, team.splice(from, 1)[0])
console.log(team)
Here I am chaning the index of the team from 0 to 5 which gives me output like:
["Green","Blue","Yellow","Black","White","Red","Orange"]
The 0 index positioned to 5.
Now I have an dictionary which contains the captain for the team according to index.
var captians = [{'index': 0, 'captain': 'Jack'}, {'index': 1, 'captain': 'Daniel'}]
Here 0 is the index of team.
Team red's captain is Jack
When team is changed in index I want to change the captains accordingly.
How can I do this ??
You could iterate over and move all indices in the interval a position.
var team = ["Red", "Green", "Blue", "Yellow", "Black", "White", "Orange"],
from = 0,
to = 5,
captians = [{ 'index': 0, 'captain': 'Jack' }, { 'index': 1, 'captain': 'Daniel' }];
team.splice(to, 0, team.splice(from, 1)[0]);
captians.forEach(function (a) {
if (a.index === from) {
a.index = to;
return;
}
if (from < to && a.index > from && a.index <= to) {
a.index--;
}
if (from > to && a.index >= to && a.index < from) {
a.index++;
}
});
console.log(captians);
Try this :
captians.map((item)=>
{
if(item['index'] == to){
item['index'] = from
}else if(item['index'] == from){
item['index'] = to
}else{
if(item['index']> from && item['index']<to){
item['index'] -=1;
}
}
})
You need objects rather than array here. Following alterations work best in this situation:
var team = {0:'Red',1:'Green',2:'Blue',3:'Yellow',4:'Black',5:'White',6:'Orange'};
var captains = {0 : 'Jack', 1: 'Daniel', 2: 'Mark',3:'Joan',4:'Sarah',5:'Mindy',6:'Stuart',7:'Jane'};
function swapTeam(from, to){
temp = team [to];
team[to] = team[from];
team[from] = temp;
temp = captains[to];
captains[to] = captains[from];
captains[from] = temp;
}
swapTeam(0,5);
console.log(team);
console.log(captains);

Categories

Resources