Declaring variable within functions - javascript

Ok, so I I'm having this strange behaviour that I cannot explain. Look at the following:
$("#completeData").on("click", function() {
var toUpdate = {};
var toUpdateCount = 0;
var ratios = {};
This.calculateGradePerSize();
//1) Select all sizes that are equal to NA or are Equal to 0 (means its a new one)
$.each(This.logements, function(key, l) {
if (l.sizeMyId === "NA" || l.sizeMyId === 0) {
toUpdate[l.rueNum] = l;
toUpdateCount++;
} else { //else init the ratios because it means they are actually present
/**
//My problem is this variable,
I want it to be equal to an empty object
But for reasons I cannot seem to understand,
it takes in account the latter modification in the code
that happens to this variables
*/
ratios[l.sizeMyId] = {};
}
});
console.log(toUpdate);
console.log(ratios);
console.log(This.sizeRatio);
//2) Calculate Ratios and build the ratios function of the toUpdate
$.each(This.sizeRatio, function(sizeMyId, count) {
if (sizeMyId !== "NA" && sizeMyId != 0) {
console.log("COUNT SIZE: " + count + " COUNT LOGEMENT: " + This.countLogement + " toUpdateCount: " + toUpdateCount + " SizeMyId: " + sizeMyId);
console.log("Calculation: " + count / This.countLogement * toUpdateCount);
ratios[sizeMyId].count = Math.ceil(count / This.countLogement * toUpdateCount);
console.log("Calculation WITH CEIL: " + Math.ceil(count / This.countLogement * toUpdateCount));
ratios[sizeMyId].grade = This.sizeGrade[sizeMyId];
ratios[sizeMyId].sizeMyId = sizeMyId;
}
});
console.log(ratios);
});
As explained in the multiline comment, my problem is the ratio variable. I tried declaring the variable without var prefix, so that JS doesn't know its existence but still, I want it to be empty object. In fact, the problem has stronger roots than simply that, I cannot update it. Each change I make to the ratios var are not registered, but I wanna start with the beginning how can I make sure that this variable is empty at the beginning of the function.

I don't know if this question is really worth. Thinking about deleting it. My bug was that the count variable in the each function as well as the ratio definition were the same hence not registering.
As for the variable not being an empty one at function start. It simply how the JS engine works. If there is something not working, more likely than not, there is something wrong in your code.
$.each(This.sizeRatio, function (sizeMyId, count) {
if (sizeMyId !== "NA" && sizeMyId != 0) {
console.log("COUNT SIZE: " + count + " COUNT LOGEMENT: " + This.countLogement + " toUpdateCount: " + toUpdateCount + " SizeMyId: " + sizeMyId);
console.log("Calculation: " + count / This.countLogement * toUpdateCount);
//HERE ratios[sizeMyId].count IS THE SAME than the anonymous function.
ratios[sizeMyId].count = Math.ceil(count / This.countLogement * toUpdateCount);
console.log("Calculation WITH CEIL: " + Math.ceil(count / This.countLogement * toUpdateCount));
ratios[sizeMyId].grade = This.sizeGrade[sizeMyId];
ratios[sizeMyId].sizeMyId = sizeMyId;
}
});

Related

How to save the function random number inside a variable [duplicate]

This question already has an answer here:
Javascript variable declared as code and reuse
(1 answer)
Closed 3 years ago.
I want to do something like this:
var randomNum = Math.floor(Math.random() * 10 + 1);
console.log("What is the answer of: " + randomNum + " + " + randomNum + "?");
console.log("What is the answer of: " + randomNum + " + " + randomNum + "?");
console.log("What is the answer of: " + randomNum + " + " + randomNum + "?");
console.log("What is the answer of: " + randomNum + " + " + randomNum + "?");
and inside the console I want it to get:
What is the answer of: 5 + 6?
when we refresh the page we should get another number for example:
What is the answer of: 3 + 1?
etc..
normal random function but with assigning it to a variable;
because when I do that it just keep printing the same number?
insde my console:
What is the answer of: 1 + 1?
second refresh
What is the answer of: 3 + 3?
third refresh:
What is the answer of: 2 + 2?
and so on, The both cells has the same value?
I can fix it without DRY (don't repeat your self) by the basic structure:
//var randomNum = Math.floor(Math.random() * 10 + 1);
console.log("What is the answer of: " + Math.floor(Math.random() * 10 + 1) + " + " + Math.floor(Math.random() * 10 + 1) + "?");
But as you know maybe I'm doing a big project so I should not repeat my self, right?
When you do it like this: var randomNum = Math.floor(Math.random() * 10 + 1);, first the right side of the expression is evaluated, then assigned into randomNum. So ofc it will stay the same.
just turn it into a function:
randomNum = () => Math.floor(Math.random() * 10 + 1);
This will work, you need to make it a function
var randomNum = () => Math.floor(Math.random() * 10 + 1);
then you can use it as randomNum()
You can simply create a function that creates 2 unique random numbers and call it upon DOMContentLoaded event being fired:
//Call your random number function when DOM is fully loaded and parsed
window.addEventListener('DOMContentLoaded', init)
function init() {
//We have to create 2 unique random numbers here (not just one):
const a = Math.floor(Math.random() * 10 + 1),
b = Math.floor(Math.random() * 10 + 1);
console.log(`${a} + ${b} = ${a + b}`);
}

Is my javascript implementation of a DP solution to Knapsack properly utilizing a memoization table?

This is my javascript implementation for the knapsack problem. In this problem, you are given a list of items with weights and values, and a knapsack with a weight capacity. The object is to determine how to maximize the value of objects you can hold in the knapsack without exceeding the weight capacity. My function below takes two parameters, items (an array of item objects, each containing a weight and value field, and a capacity integer representing the knapsack weight capacity. I use a memo table in which each index:weight is stored for repeated access to avoid duplicate calculations of getMax(). Is my implementation good? Can it be improved?
function knapsackMaxValue(items, capacity) {
const memo = {}
function getMax(i, weight) {
if (i == items.length) {
return 0;
}
if (memo[i + ':' + weight] != undefined) {
console.log('memo found')
return memo[i + ':' + weight]
}
if (items[i].weight + weight > capacity) {
memo[i + ':' + weight] = getMax(i + 1, weight)
return memo[i + ':' + weight]
} else {
let maxValue = Math.max(getMax(i + 1, weight), items[i].value + getMax(i + 1, weight + items[i].weight))
memo[i + ':' + weight] = maxValue
return maxValue
}
}
return getMax(0, 0)
}

How to store results of an iteration in a variable

For educational reasons, I am working through a simple algorithm that randomly generates two numbers and then asks for the addition of generated numbers, tells you if you are right or wrong on response, and tracks results out of 100. I would like to include function that reports something like the following: "You have gotten 80/100 correct" But am held up with syntax, I think. I can't get my score variable to count up with correct answers.
Here is my code as it stands..
do{
var firstnum = Math.floor(Math.random()*10);
var secondnum = Math.floor(Math.random()*10);
var result = firstnum+secondnum;
var score=0;
var answer = prompt("what is "+firstnum + "+" + secondnum);
if(answer < result || answer > result){alert("Wrong! " + "The correct answer
is " + result)};
if(answer == result){alert("you are correct!"), score++};
alert("Awesome, You have gotten " + score + " correct so far!!!");}
while(score<100);
Just get me over the hump. I am hopeful that I can really get my head wrapped around more concepts if I can get through this little guy.
You reset score in every loop to zero. Move the declaration and initialization to top.
Some hints:
no need for semicolons after a block statement { /* code */ },
convertion of strinn to number with unary plus +
use a single if statement with else block for the opposite of the check.
// declare all variables at top
var firstnum,
secondnum,
result,
score = 0,
answer;
do {
firstnum = Math.floor(Math.random() * 10);
secondnum = Math.floor(Math.random() * 10);
result = firstnum + secondnum;
// covert input string to number with unary plus
answer = +prompt("what is " + firstnum + "+" + secondnum);
// ^
// just check the result and omit a second if clause,
// because it is just the opposite check
// take the more easy/shorter check first
if (answer === result ) {
alert("you are correct!");
score++;
} else {
alert("Wrong! " + "The correct answer is " + result)
}
alert("Awesome, You have gotten " + score + " correct so far!!!");
} while (score < 2) // take a small number for scoring check

How to prevent a new object of robots from going to the same location as previous robots?

Things you need to know about my Program
I have created a program in JavaScript that executes Robot instruction that you give. per Robot Object.
The robot is inside a rectangle shaped area. It moves with (x,y) points. Such that (0 <= x <= 50) and (0 <= y <= 50)
The instructions are in Strings of continuous of three repeated letters - There are Three letter that represent the movement of the robot
The program runs each letter and moves the robot according to the letter.
If the program finds out the the robot is out of the surface. Then the robot is lost and the coordinates of that particular robot is kept in array of lists called Lost_Robot
My Question:
I don't know how to prevent a new robot from going to the same coordinates that a previous robot got lost (because of out of Rectangle surface).
How can I achieve from preventing another new robot (when I say new Robot, I mean new Robot Object) from jumping to the same location that a previous robot went and got lost.
I have an array of (x,y) of robots that got lost. But how can I use this array from letting a new robot going to this point?
I tried to use for loop that runs the array to see the coordinates, but doesn't do anything.
Also
While your working on my problem, can you also give me few hints on how can I simplify my code yet doing the same functionality, but more efficiently.
=
var orientation = ["N", "E", "S", "W"];
var instruction = ["L", "R", "F"];
var lost_Robot_Scent = [];
// function created for assigning coordinates and an orientation
function Robot_Coordinatation(x, y, orientation) {
// coordinate (x,y) must be located at (0,0) at the initial state of the program
this.x = 0;
this.y = 0;
// orientation assigned
this.orientation = orientation;
// this is printed for the purpose of tidiness
document.write("============================" + "<br />");
// | ( x,y) | e.g(S)
document.write("| ( " + x + ", " + y + " ) | " + orientation + "<br />");
// We have a nested function here that will determine the movement/instruction of the robot
this.Robot_Instruction = function(instruct_The_Robot) {
// We are making sure here that the length of the instruction is less than 100
if (instruct_The_Robot.length <= 100) {
// if...statement - if x & y is bigger than or equal to 0 and smaller than or equal to 50 -> If its true then go inside the if statment.
// Essentiallly, what this statement is actually doing is that its creating the rectangular grid.
if ((x <= 50 && x >= 0) && (y <= 50 && y >= 0)) {
// itterate the array of the instruct_The_Robot
for (var i = 0; i < instruct_The_Robot.length; i++) {
// if any value of instruct_The_Robot is strictly equal to "L", then go inside this if statement. refer to line: 10
if (instruct_The_Robot[i] === instruction[0]) {
// variable Left declared and instantiated with -90°
var Left = -90 + "&#176";
// variable result instantiated with value (x,y) & orientation
var result = " | ( " + x + ", " + y + " ) " + " | " + orientation + " " + Left + "<br />";
// however, if the if...statment at line: 33 is not true, then follow this : if the value of instruct_The_Robot is equal to "R"...
} else if (instruct_The_Robot[i] === instruction[1]) {
// variable Right instantiated with 90°
var Right = 90 + "&#176";
// variable result instantiated
var result = " | ( " + x + ", " + y + " ) " + " | " + orientation + " " + Right + "<br />";
// however, if the if...statment at line: 33 & elseif at line: 39 is not true, then if instruct_The_Robot is equal to "F"...
} else if (instruct_The_Robot[i] === instruction[2]) {
// variable y_Plus_One is instantiated with the current value of y and moves y one point forward
var y_Plus_One = y += 1;
// if the negation of x & y_Plus_One is smaller than 50 and bigger the 0, then...
if (!((x <= 50 && x >= 0) && (y_Plus_One <= 50 && y_Plus_One >= 0))) {
// then print " lost! "
document.write("LOST!" + "<br />");
// & keep the record of the x and y_Plus_One value to the lost_Robot_Scent array
lost_Robot_Scent.push([x, y]);
// and return false - this stops printing "Lost!" more than one times
return false;
// Otherwise, if the above doesn't satisfy, then...
} else {
// variable result instantiated with the updated coordinates (y_Plus_One)
var result = " | ( " + x + ", " + y_Plus_One + " ) " + " | " + orientation + " " + "<br />";
}
}
}
//print the result
document.write(result);
// if none of the if...statement above satisfy, then...
} else {
// variale lost instantiated with "Lost!" message
var lost = "LOST!" + "<br />";
// push the robot to the lost_Robot_Scent
lost_Robot_Scent.push("| ( " + x + ", " + y + " ) " + "<br />");
}
} else {
alert("There is alot of of instructions given. Please make sure that the instruction is less than 100 instructions");
}
}
}
// new Robot object initialised
var one = new Robot_Coordinatation(50, 50, orientation[1]);
one.Robot_Instruction("LRLRLRLRLRLLRRLRLRLLRLLRRLL");
var two = new Robot_Coordinatation(20, 30, orientation[3]);
two.Robot_Instruction("FFFLLFLRLFLRFLRLLLFRL");
var two = new Robot_Coordinatation(30, 7, orientation[3]);
two.Robot_Instruction("FFFFLRLFLRFLRL");
Maintaining lost_Robot_Scent
I can help you with keeping a collection of locations where your robots get lost (your lost_Robot_Scent array). I suggest using a Set instead on an Array. Sets provide O(1) insertion and O(1) lookup. This probably isn't a big deal in this situation, but it's good to know about Set anyway.
The main problem you'll run into is that array equality is pointer equality: for example, [1, 1] === [1, 1] returns false. One workaround is using toString() on the arrays and storing that in the Set. For example:
var lost_Robot_Scent = new Set();
lost_Robot_Scent.add( [1, 1].toString() );
lost_Robot_Scent.has( [1, 1].toString() ); // -> true
lost_Robot_Scent.has( [2, 2].toString() ); // -> false
I don't know if this is the cleanest solution, but it works. If you want to use an Array instead of a Set, just use push instead of add and includes (or indexOf) instead of has, e.g.
var lost_Robot_Scent = [];
lost_Robot_Scent.push( [1, 1].toString() );
lost_Robot_Scent.includes( [1, 1].toString() ); // -> true
lost_Robot_Scent.includes( [2, 2].toString() ); // -> false
If you are worried about performance, you can test these two methods against each other in specific contexts.
Improve The Code
One thing you can do to simplify your code is to lessen the nested if statements. For example, the first if in your Robot_Instruction function could be
if (instruct_The_Robot.length > 100) {
alert("Too many instructions! Please limit to 100."
return;
}
// continue...
Perhaps this is a bit off-topic, but you should only use comments for things are aren't obvious. For example, variable Left declared and instantiated with -90° is unnecessary.
One last thing: you can simplify the "instructions" loop using a switch statement instead of if/else blocks. Or, if you want to make is super-readable, you can use a JavaScript object like so:
var move = {
L: function() {
// turn left
},
R: function() {
// turn right
},
F: function() {
// move forward
},
};
// then, in the "instructions" loop, you can just do
for (var i = 0; i < instruct_The_Robot.length; i++) {
move[ instruct_The_Robot[i] ]();
}
That's a pretty neat trick.
How to prevent a new robots from getting lost in the same places as old robots
Assuming you've fixed your bugs, and robots are moving. When you determine that a robot is moving forward, you have to determine if the new coordinates are already in the lost_Robot_Scent array. You can do this using something like the following:
var robotLostAtSameLocation = false;
for (var i = 0; i < lost_Robot_Scent.length; i++) {
var lostRobotLocation = lost_Robot_Scent[i];
if(lostRobotLocation[0] === x && lostRobotLocation[1] === y) {
robotLostAtSameLocation = true;
break;
}
}
if (robotLostAtSameLocation) {
// whatever you want to do in this case
}
else {
// whatever you want to do in this case
}
Simple optimization
Note that you can get rid of this loop if you change the lost_Robot_Scent array from containing [x,y] to containing something like 'x:y'. So rather than an array that contains other arrays looking like this: [[39,51], [51,15], [-1,11]], it will be an array containing strings looking like: ['39:51', '51:15', '-1:11']. What this buys you is that you can then just say var robotLostAtSameLocation = lost_Robot_Scent.indexOf(x + ':" + y) > -1;
Recommendation
Change var instruction = ["L", "R", "F"]; into something more like var INSTRUCTIONS = {LEFT: 'L', RIGHT: 'R', FORWARD: 'F'};. This turns lines like instruct_The_Robot[i] === instruction[0] into instruct_The_Robot[i] === INSTRUCTIONS.LEFT, improving readability.
Bugs
You are never updating x, y, or orientation. Your robots are never moving. You are only outputting a string.
You are only checking if the y-coordinate is out of bounds. You are forgetting to check if the x-coordinate is out of bounds.
You are pushing [x,y] into the lost_Robot_Scent array on one line, then pushing "| ( " + x + ", " + y + " ) " + "<br />" into the same array on another line. Don't do that. It's hard to reason about a program when it is not consistent.
There may be other issues - I can't take the time to fully digest it at the moment.

Result of a while loop still happens even when the condition isn't met

I'm practising writing Javascript by making a Roguelike dungeon game but there is a problem when I want to create monsters. I have written a while loop such as:
this.getRandomCoordinatesInRoom = function(roomNumber) {
var validLocationFound = false;
while (!validLocationFound){
// Generate co-ords in room first
x = Math.floor(Math.random() * (this.roomList[roomNumber].width) + (this.roomList[roomNumber].posX));
y = Math.floor(Math.random() * (this.roomList[roomNumber].height) + (this.roomList[roomNumber].posY));
// Find location of (x,y) in Dungeon Array
//alert(arrayLocation);
var tmpX = ((this.roomList[roomNumber]).posX + x);
var tmpY = ((this.roomList[roomNumber]).posY + y);
var arrayLocation = ((tmpY * 80) + tmpX);
//var arrayLocation = ((this.roomList[roomNumber].posX + x) + (80 * (this.roomList[roomNumber].posY + y)));
if (this.dungeonArray[(tmpY + tmpX)] === "floor") {
validLocationFound = true;
};
if ((x<this.roomList[roomNumber].posX) || (x>(this.roomList[roomNumber].posX + this.roomList[roomNumber].width))){
alert("x out of bounds");
};
if ((y<this.roomList[roomNumber].posY) || (y>(this.roomList[roomNumber].posY + this.roomList[roomNumber].height))){
alert("y out of bounds");
};
writeToScreen("Room upper left corner = " + (this.roomList[roomNumber].posX).toString() + "," + (this.roomList[roomNumber].posY).toString(),10);
return [x,y];
if (!(getTileAt(arrayLocation) === "floor")){
alert("It messed up");
}
};
The code randomly generates an x,y coordinate and converts it to a single number (My dungeon array is one dimensional, 0-79 across and then 80 is a new row). however, even when the code generates a coordinate that isn't valid (!= "floor"), it still finishes the function as though it returned true. Why is this?
Your function returns [x,y] from inside the while loop. Declare the variables outside of the loop and then return the value from outside the loop. Or else, return is when validLocationFound is true.
var x, y ;
while(...) {
...
}
return [x, y];

Categories

Resources