(FunctionReturn() - 1) fails but (-1 + FunctionReturn()) succeeds? - javascript

I have a getter/setter function that returns an absolute value. So I presumed that JavaScript would allow me to perform arithmetic with it. But it only works in a certain order...
NOTE: pos.get("log", pos.get("log") + 1) always returns 1 in these examples.
console.log("initial log: " + (-1 + pos.get("log", pos.get("log") + 1)));
// PSEUDO-CODE: -1 + (log += 1)
// RESULT: 0
The above code works as expected. But switch around the order and it all changes... Despite pos.get() always returning an absolute value of the same type. (Number)
console.log("initial log: " + (pos.get("log", pos.get("log") + 1) - 1));
// PSEUDO-CODE: (log += 1) - 1
// RESULT: 1
If log was equal to 0 from the beginning, the first console.log() prints 0. However, the second prints 1. I get no errors in the console whatsoever. Took me a while to figure out that the "- 1" was just being completely disregarded.
Why?
EDIT: Definition of pos.get()
get: function(str, val) {
switch(str) {
case "start": {
if(val != undefined) {
start = val;
}
return start;
}
case "log": {
if(val != undefined) {
log = val;
}
return log;
}
case "offset": {
if(val != undefined) {
offset = val;
}
return offset;
}
}
}

Be sure that your function returns a number (e.g. float), eventually with parseFloat(). Now, I think the js parser doesn't know.
With 1 - yourFunction() the js parser suggests that the return value of your function is numeric.

Related

adding values that could contain a null/undefined value

I'm sorry to ask, but I just can't find the info.
My script needs to add 12 items together but some of them may have null/undefined values
ie
1 + null + 3 + 4 + null + null + 7
How do I add these together?
$scope.wepweight = ($scope.selectedWeapon1Ship1.Vars.weight) +($scope.selectedWeapon2Ship1.Vars.weight)
At the moment, the values will add together once all the ng-models are populated (because of the null/undefined values), but I need to keep a running total.
https://jsfiddle.net/wayneker/3u6ob98d/2/
(search for "//calculate weight for hull" within the JS section to see the relevant section of code)
You could take the Nullish coalescing operator ?? which checks if the value is null or undefined, then it takes the right hand side value.
const sum = 1 + (null ?? 0) + 2 + (undefined ?? 0);
console.log(sum);
You can use the || operator to check if the value is null or undefined, and if it is, add 0 to it:
console.log(1 + (null || 0) + 3 + 4 + (undefined || 0) + 7) // 15
You didn't specify where you got your values from, but either they are stored in an array or you can put them in an array.
Once you have them in an array, it's elegant with reduce:
// assuming weight is your array
weight.reduce((a,b) => typeof b === 'number' ? a + b : a, 0);
What this code does is that it starts with 0 and adds every element that is a number (which null is not)
i think this one can help you
$scope.wepweight = calcSumValue();
function calcSumValue() {
let ans = 0;
for(let i = 1; i <= 12; i++) {
const value = $scope[`selectedWeapon${i}Ship1`].Vars.weight
if (value)
ans += value;
}
return ans;
}

LocalStorage isn't passing the number 9

I'm am having problems with localStorage, my localStorage isn't passing the number 9. What can I do to resolve this problem?
I've tried so many things, but nothing works.
I am doing this:
if (typeof(Storage) !== "undefined") {
if (sessionStorage.pontos) {
sessionStorage.pontos = Number(sessionStorage.pontos) + 1;
} else {
sessionStorage.pontos = 1;
}
document.getElementById('pontos').innerHTML = "PONTOS: " + sessionStorage.pontos;
} else {
document.getElementById('pontos').innerHTML = "ERROR";
}
if (typeof(Storage) !== "undefined") {
if (sessionStorage.pontos > localStorage.Recpontos) {
localStorage.Recpontos = Number(localStorage.Recpontos) + 1;
}
}
This action happen when click in a button.
And I go to the browser console, and nothing, in the console show this:
> localStorage.Recpontos
"9"
> sessionStorage.pontos
"10"
And it was not to be happening this, because when the sessionStorage.pontos is greater than localStorage.Recpontos was for the two to be in the same value. And 9 has only one place, and 10 has two, I think this is the problem.
I expected the localStorage.Recpontos will be added 1 when the sessionStorage.point is larger than it.
You need to compare the values as numbers, not strings.
if (Number(sessionStorage.pontos) > Number(localStorage.Recpontos)) {
localStorage.Recpontos = Number(localStorage.Recpontos) + 1;
}
If you compare them as strings, it performs a lexicographic comparison, and "10" < "9" because "1" < "9".

How to explain cached fibonacci algorithm complexity

I'm trying to explain correctly cached fibonacci algorithm complexity. Here is the code (https://jsfiddle.net/msthhbgy/2/):
function allFib(n) {
var memo = [];
for (var i = 0; i < n; i++) {
console.log(i + ":" + fib(i, memo))
}
}
function fib(n, memo) {
if (n < 0) return 0;
else if (n === 1) return 1;
else if (memo[n]) return memo[n];
memo[n] = fib(n - 1, memo) + fib(n - 2, memo);
return memo[n];
}
allFib(5);
The solution is taken from "Cracking the coding interview" and adapted to javascript.
So here is a "not very nice" tree of function calls
I was thinking like that: "The left most branch (bold one) is where the evaluation is happening" and it is definitely the number passed to the allFib function for the first time. So the complexity is O(n). Everything that is to the right will be taken from cache and will not require extra function calls". is it correct? also how to connect this to the tree "theory". The depth and the height of the tree in this case is 4 but not 5 (close to n but not it). I want the answer to be not intuitive but more reliable.
Here is a function that really uses the cache:
function Fibonacci() {
var memo = [0, 1];
this.callCount = 0;
this.calc = function(n) {
this.callCount++;
return n <= 0 ? 0
: memo[n] || (memo[n] = this.calc(n - 1) + this.calc(n - 2));
}
}
var fib = new Fibonacci();
console.log('15! = ', fib.calc(15));
console.log('calls made: ', fib.callCount);
fib.callCount = 0; // reset counter
console.log('5! = ', fib.calc(5));
console.log('calls made: ', fib.callCount);
fib.callCount = 0;
console.log('18! = ', fib.calc(18));
console.log('calls made: ', fib.callCount);
The number of function calls made is:
(n - min(i,n))*2+1
Where i is the last entry in memo.
This you can see as follows with the example of n = 18 and i = 15:
The calls are made in this order:
calc(18)
calc(17) // this.calc(n-1) with n=18
calc(16) // this.calc(n-1) with n=17
calc(15) // this.calc(n-1) with n=16, this can be returned from memo
calc(14) // this.calc(n-2) with n=16, this can be returned from memo
calc(15) // this.calc(n-2) with n=17, this can be returned from memo
calc(16) // this.calc(n-2) with n=18, this can be returned from memo
The general pattern is that this.calc(n-1) and this.calc(n-2) are called just as many as times (of course), with in addition the original call calc(n).
Here is an animation for when you call fib.calcfor the first time as fib.calc(5). The arrows show the calls that are made. The more to the left, the deeper the recursion. The bubbles are colored when the corresponding result is stored in memo:
This evidently is O(n) when i is a given constant.
First, check for negative n, and move the value to zero.
Then check if a value is cached, take the value. If not, assign the value to the cache and return the result.
For the special cases of n === 0 or n === 1 assign n.
function fibonacci(number) {
function f(n) {
return n in cache ?
cache[n] :
cache[n] = n === 0 || n === 1 ? n : f(n - 1) + f(n - 2);
}
var cache = [];
return f(number);
}
console.log(fibonacci(15));
console.log(fibonacci(5));
Part with predefined values in cache, as Thomas suggested.
function fibonacci(number) {
function f(n) {
return n in cache ?
cache[n] :
cache[n] = f(n - 1) + f(n - 2);
}
var cache = [0, 1];
return f(number);
}
console.log(fibonacci(15));
console.log(fibonacci(5));

Saving data using promises

On Parse.com I have the following function, and my question follows:
function myFunction(array, value) {
var logMessage;
logMessage = "array: " + array.length.toString();
console.log(logMessage);
if (!array.length) return;
if (!value) value = Math.min(10, array.length);
if (array[array.length - 1].get("advertisePointNumber") >= value) return;
var classPromise;
array[array.length - 1].set("advertisePointNumber", value);
logMessage = "(BIS)array: " + array.length.toString();
console.log(logMessage);
classPromise = (array[array.length - 1].save(null, {}).then(function (object) {
logMessage = "HERE I AM!!!";
console.log(logMessage);
if (array.length == 1) return;
array.splice(array.length - 1, 1);
return myFunction(array, value);
}, function (error) {
// saving the object failed.
console.log("error:" + error);
}));
logMessage = "(TER)array: " + array.length.toString();
console.log(logMessage);
return Parse.Promise.when(classPromise);
}
The question is what am I missing? I never see the message "HERE I AM!!!" (and no error either) in the logs and as a consequence the recursive call that I wish is not working.
I have successfully used similar code in the past, when reading data. Here I am saving data. I must be doing something the wrong way. What is it?
Update to the question:
Calling this function with the following line of code:
myFunction(myArray, 0);
I get the log below:
I2015-06-22T07:05:34.160Z]myArray: 2 // Number of elements in the initial Array.
I2015-06-22T07:05:34.161Z]array: 2
I2015-06-22T07:05:34.162Z](BIS)array: 2
I2015-06-22T07:05:34.163Z](TER)array: 2
I would expect to see :
I2015-06-22T07:0.....]array: 1
after the above but I do not see anything.
Instead of going for recursive, you can try this:
classPromise = array.map(function(obj){ return obj.save();});
in es6, same thing can be:
classPromise = array.map(obj => obj.save());
Edit
You can reduce the whole function to:
function myFunction(array, value) {
if ( !array || !array.length) return;
console.log("array: " + array.length);
if (!value) value = Math.min(10, array.length);
var pSave=[], i = array.length, v2=(value)? value : Math.min(10, i);
while(i>0 && array[i-1].get("advertisePointNumber") >= value){
array[i - 1].set("advertisePointNumber", value);
pSave.push(array[i - 1].save());
console.log("(BIS)array: " + i);
i--;
v2=(value)? value : Math.min(10, i);
}
return Parse.Promise.when(pSave);
}
if you wanted it to be saved sequentially,
...
var pSave = Parse.Promise.as(1),
...
pSave.then(function(){
return array[i-1].save();
});
...
return pSave;
}
You don't need to pass null as the 1st parameter
You don't need to use both save with options (2nd parameter), and save with promises chain (.then)
So, just remove both the first and the second parameter of save function as follows
array[array.length - 1].save().then(...
Updated Answer
You should use multiple save calls in promises chain instead of recursive one like the below
function myFunction(array, value) {
var logMessage;
logMessage = "array: " + array.length.toString();
console.log(logMessage);
if (!array.length) return;
if (!value) value = Math.min(10, array.length);
var savePromises = Parse.Promise.as();
array.map(function(element, index) {
// Calculate value based on your needs
if(element.get("advertisePointNumber") < value) {
element.set("advertisePointNumber", value);
}
savePromises = savePromises.then(function() {
return element.save();
});
});
return savePromises.then(function (object) {
logMessage = "HERE I AM!!!";
console.log(logMessage);
}, function (error) {
// saving the object failed.
console.log("error:" + error);
});
}
OR if you have the option to make cloud code to save them in one request, you should do, to reduce network requests

Reduce function to take an undefined initial value

I want to create a function (reduce) that does the following:
Where:
var collection = [1, 2, 3];
and
function iterator(total, element) {
return total + element;
};
if initial is defined as 3:
reduce(collection, iterator, 3)
will do this:
3 + 1
4 + 2
6 + 3 = 9
if initial is undefined:
reduce(collection, iterator)
will do this:
1 + 2
3 + 3 = 6
Here is my code:
var reduce = function(collection, iterator, initial) {
if (initial === undefined) {
var total = 0;
} else {
var total = initial;
}
each(collection, function(element) {
total = iterator(total, element);
});
return total;
}
It works, but you can see that I've hard-coded total = 0, but I want this code to work in other scenarios (for example, multiplication, where I wouldn't want 0 to make the whole product 0).
This is how I would implement it:
alert(reduce([1,2,3], add, 3)); // 9
alert(reduce([1,2,3], add)); // 6
function add(a, b) {
return a + b;
}
function reduce(array, iterator, initial) {
var length = array.length;
var index = 0;
if (arguments.length < 3) {
if (length > 0) var result = array[index++]; // Note 1
else throw new Error("Reduce of empty array with no initial value");
} else var result = initial;
while (index < length) result = iterator(result, array[index++]);
return result;
}
The code is pretty self explanatory. Nevertheless, here's how it works, if the number of arguments passed are less than 3 it means that initial was not given. Hence we set result to array[0] and increment index. If array is empty then we throw an error instead. Otherwise we set the result to the initial value passed to the function. Everything else works as normal.
Note 1: The reason we don't modify initial (i.e. write initial = array[index++]) is because if we use arguments in a function and also modify the parameters of the function then the function will not be optimized in V8. Hence, it will execute slower.
Hope this helps.

Categories

Resources