JavaScript assignment with operation *= conundrum - javascript

Following code is giving me a big time headache
var somearr = [1, 2, 3];
function operations() {
for (var i = 0; i < somearr.length;) {
//alert (somearr[i++] *= 2); // statement-1
alert(somearr[i++] = somearr[i++] * 2); //statement-2
}
}
operations();
Conceptually statement-1 and statement-2 are same (see the comments in the code above). I know that somearr[i++] is evaluated once in statement-1 and twice in statement-2. However what I don't understand is that output of statement-1 (after recursive iteration) is [2,4,6] which is expected but the output of the recursively executing statement-2 is [4,NaN] (totally confused with this output).
On top of that when I try to debug this code using Visual Studio and put a break point in front of statement-2 when the break point is hit I just stay at the statement-2 (forever) without debugging the code any further and noticed (nearly after every 10 to 15 seconds) that index value i++ automatically gets incremented without even debugging the code further (as I said earlier) , I'm kinda totally stumped that how come visual studio debugger auto increments index i value without letting me debug the code (that is, recursively iterating all the index values) and stops increment once the value if i++ = 3.

Your issue is that you're incrementing i twice in statement 2. So multiplying by null (which is what you get when you pull an index not in your array) returns NaN.
It is best practice to increment inside your for-loop like this:
for (var i = 0; i < somearr.length; i++) {
//somearr[i] *= 2; // statement-1
//somearr[i] = somearr[i] * 2; //statement-2
}
Now both statements work.
your code was as follows:
for (var i = 0; i < somearr.length;) {
somearr[i++] = somearr[i++] * 2;
}
At execution we evaluate somearr[i++]:
i = 0, somearr[0] = 1
We set this to equal to somearr[1] * 2 (somearr[1] since we incremented after our first evaluation).
Therefore the first index of somearr becomes 4, and i is currently set to 2, since we incremented again.
Now we check somearr[2], which gives us 3. We set this value to equal somearr[3] * 2. But somearr[3] is null, because we are now past the array's indices. This evaluates to NaN because 2*null is NaN.
our i is now 4, because we incremented again, and our array is [4, NaN]. We stop looping because i = 4, which terminates the for-loop

the output of statement-1 is [2,4,6] which is expected
Yes. If we unroll the loop, we get
var somearr = [1, 2, 3];
somearr[0] *= 2; // somearr[0] = somearr[0] * 2;
somearr[1] *= 2; // somearr[1] = somearr[1] * 2;
somearr[2] *= 2; // somearr[2] = somearr[2] * 2;
// i (3) is no more smaller than somearr.length (3) after the third iteration
the output of executing statement-2 is [4,NaN] (totally confused with this output).
Actually the output of somearr is [4, 2, NaN]. Why is that? Because i++ is evaluated twice per body execution. The loop now unrolls to
var somearr = [1, 2, 3];
somearr[0] = somearr[1] * 2; // 2 * 2
somearr[2] = somearr[3] * 2; // undefined * 2
// i (4) is no more smaller than somearr.length (3) after the second iteration

Related

Finding the greatest prime factor of an integer in Javascript

I am trying to write a simple program to find the greatest prime factor of an integer in JavaScript. The code I have written to do this follows:
let ans;
function factor(target, half) {
for (let i = 2; i < half; i++) {
if (target % i == 0) {
ans = target / i;
factor(ans, ans / 2);
}
}
}
factor(30, 15);
console.log(ans);
Now whether or not this code is an efficient solution to the problem or if it even works at all is beyond my issue with it: When I follow breakpoints set at each line of the factor function, I see that right after i = 2, target = 5, half = 2.5, and ans = 5, the value of target and half jump back up to 15 and 7.5 respectively. However, I do not see where in my code the values are told to change.
You're calling the function recursively, and each call to the function gets its own target, half, and i variables. In the first call to factor, target is 30 and half is 15. Then you call it again with the arguments 15 and 7.5; that inner call to factor gets its own target (15) and half (7.5), but the outer call still has its copies (30) and (15). This continues when you call factor again recursively, creating a third set, etc. When you step out of the innermost call, its variables disappear and you see the ones that are for the call that called it.
It may be clearer with a simpler example:
function countdown(value, indent) {
var twice = value * 2;
console.log(indent + "[before] value = " + value + ", twice = " + twice);
if (value > 0) {
countdown(value - 1, indent + " ");
}
console.log(indent + "[after] value = " + value + ", twice = " + twice);
}
countdown(3, "");
.as-console-wrapper {
max-height: 100% !important;
}
The output of that is:
[before] value = 3, twice = 6
[before] value = 2, twice = 4
[before] value = 1, twice = 2
[before] value = 0, twice = 0
[after] value = 0, twice = 0
[after] value = 1, twice = 2
[after] value = 2, twice = 4
[after] value = 3, twice = 6
As you can see, the values for value and twice in the outer call aren't changed by making the inner call. Each call gets its own set of variables.

A simple for loop questions about -1 and i--

I have what I think surely is a really simple question for most of you. But I have some trouble to get my head around this for loop. What does the -1 in argument.length -1 stand for? Is it the last item? And the i-- that is for decrease by 1?
var plus = function() {
var sum = 0;
for (var i = arguments.length - 1; i >= 0; i--) {
sum += arguments[i];
}
return sum;
}
console.log(plus(2,2,3,657,5643,4465,2,45,6));
When you call arguments.length It will return you the number of elements with the last one accessed with arguments[arguments.length-1] because counting starts with 0.
(the First element is accessed like this arguments[0]).
Here is good documentation for Java but it is the same for JavaScript: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
And yes i-- decreases i for 1. It is different i-- and --i.
Using ++/-- After the Operand
When you use the increment/decrement operator after the operand, the value will be returned before the operand is increased/decreased.
Check out this example:
// Increment
let a = 1;
console.log(a++); // 1
console.log(a); // 2
// Decrement
let b = 1;
console.log(b--); // 1
console.log(b); // 0
When we first log out the value of a, or b, neither has changed. That’s because the original value of the operand is being returned prior to the operand being changed. The next time the operator is used, we get the result of the +1, or -1.
Using ++/-- Before the Operand
If you’d rather make the variable increment/decrement before returning, you simply have to use the increment/decrement operator before the operand:
// Increment
let a = 1;
console.log(++a); // 2
console.log(a); // 2
// Decrement
let b = 1;
console.log(--b); // 0
console.log(b); // 0
As you can see in the above example, but using ++ or -- prior to our variable, the operation executes and adds/subtracts 1 prior to returning. This allows us to instantly log out and see the resulting value.
The - 1 means to subtract 1 from arguments.length. i-- means to decrease i by 1.
You need to know two things here:
arguments is a object type so it has key-value pair of values you passed as a argument into a function. Furthermore, the arguments object is not an Array. It is similar to an Array, but does not have any Array properties except length.
The key of arguments always starts with 0 and ends with one value less than the length of arguments. See the example below the key ends at 8 so you do arguments.length - 1 so that you get 8 instead of 9.
And since you are looping considering the last value first in arguments you do --i.
var plus = function() {
console.log(arguments);
console.log(typeof arguments);
var sum = 0;
for (var i = arguments.length - 1; i >= 0; i--) {
sum += arguments[i];
}
return sum;
}
console.log(plus(2, 2, 3, 657, 5643, 4465, 2, 45, 6));
Alternatively, you can also do i++ as,
var plus = function() {
var sum = 0;
for (var i = 0; i <arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
console.log(plus(2, 2, 3, 657, 5643, 4465, 2, 45, 6));

Project Euler Q#2 in "javascript"

the sum of even Fibonacci numbers below 4 mill : i am trying to do it using JavaScript, but i am getting infinity as an answer
but if i use small number such as 10, i am getting console.log() output with the result, is it possible to do that in JavaScript??
var fib = [1, 2];
for(var i =fib.length; i<4000000; i++)
{
fib[i] = fib[i-2] + fib[i-1];
}
//console.log(fib);
var arr_sum = 0;
for(var i = 0; i < fib.length; i++){
if(fib[i] % 2 === 0){
arr_sum += fib[i] ;
}
}
console.log(arr_sum);
So this is the problem:
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
The correct answer is 4613732.
On the script below, the answer would be from variable "sum". I assigned it an initial value of 2 since that is the first even number on our sequence. I used 3 more variables to traverse through this sequence. The loop runs normal Fibonacci sequence and the if statement filters even numbers and adds it to the sum.
I think this is the simplest and most intuitive code implementation.
var sum = 2;
var x = 1, y = 2, fib;
while(x < 4000000) {
fib = x + y;
x = y;
y = fib;
if(fib%2===0) sum += fib;
}
console.log(sum);
Two things before I get to coding:
You need to sum the even fibonacci numbers which VALUE below 4 Million (#Alnitak)
There is an "even fibonacci series" which can be calculated in a different manner, see here.
Alright here we go:
let fib = [0, 2];
for(let i = 2; fib[i-1] < 4000000; i++) {
fib[i] = 4 * fib[i - 1] + fib[i - 2];
}
fib.pop()
let sum = fib.reduce((a, c) => a + c, 0);
console.log(sum);
Edit
Without the fib.pop() I just added, the last element of the array would be a number > 4000000. Now you should be able to get the right result.

Finding the nth item in a repeating list of fixed items

I have to determine the mathematical formula to calculate a particular repeating position in a series of numbers. The list of numbers repeats ad infinitum and I need to find the number every n numbers in this list. So I want to find the *n*th item in a list of repeating y numbers.
For example, if my list has 7 digits (y=7) and I need every 5th item (n=5), how do I find that item?
The list would be like this (which I've grouped in fives for ease of viewing):
12345 67123 45671 23456 71234 56712 34567
I need to find in the first grouping number 5, then in the second grouping number 3, then 1 from the third group, then 6, then 4, then 2, then 7.
This needs to work for any number for y and n. I usually use a modulus for finding *n*th items, but only when the list keeps increasing in number and not resetting.
I'm trying to do this in Javascript or JQuery as it's a browser based problem, but I'm not very mathematical so I'm struggling to solve it.
Thanks!
Edit: I'm looking for a mathematical solution to this ideally but I'll explain a little more about the problem, but it may just add confusion. I have a list of items in a carousel arrangement. In my example there are 7 unique items (it could be any number), but the list in real terms is actually five times that size (nothing to do with the groups of 5 above) with four sets of duplicates that I create.
To give the illusion of scrolling to infinity, the list position is reset on the 'last' page (there are two pages in this example as items 1-7 span across the 5 item wide viewport). Those groups above represent pages as there are 5 items per page in my example. The duplicates provide the padding necessary to fill in any blank spaces that may occur when moving to the next page of items (page 2 for instance starts with 6 and 7 but then would be empty if it weren't for the duplicated 1,2 and 3). When the page goes past the last page (so if we try to go to page 3) then I reposition them further back in the list to page one, but offset so it looks like they are still going forwards forever.
This is why I can't use an array index and why it would be useful to have a mathematical solution. I realise there are carousels out there that do similar tasks to what I'm trying to achieve, but I have to use the one I've got!
Just loop every 5 characters, like so:
var data = "12345671234567123456712345671234567";
var results = [];
for(var i = 4; i < data.length; i += 5){
results.push(data[i]);
}
//results = [5, 3, 1, 6, 4, 2, 7]
If you want to use a variable x = 5; then your for loop would look like this:
for(var i = x - 1; i < data.length; i += x){...
There is no need to know y
If your input sequence doesn't terminate, then outputting every nth item will eventually produce its own repeating sequence. The period (length) of this repetition will be the lowest common multiple of the period of the input sequence (y) and the step size used for outputting its items (x).
If you want to output only the first repetition, then something like this should do the trick (untested):
var sequence = "1234567";
var x = 5;
var y = sequence.length;
var count = lcm(x, y);
var offset = 4;
var output = [];
for (var i = 0; i < count; i += x)
{
j = (offset + i) % y;
output.push(sequence[j]);
}
You should be able to find an algorithm for computing the LCM of two integers fairly easily.
A purely mathematical definition? Err..
T(n) = T(n-1) + K For all n > 0.
T(1) = K // If user wants the first element in the series, you return the Kth element.
T(0) = 0 // If the user want's a non-existent element, they get 0.
Where K denotes the interval.
n denotes the desired term.
T() denotes the function that generates the list.
Lets assume we want every Kth element.
T(1) = T(0) + K = K
T(2) = T(1) + K = 2K
T(3) = T(2) + K = 3K
T(n) = nk. // This looks like a promising equation. Let's prove it:
So n is any n > 1. The next step in the equation is n+1, so we need to prove that
T(n + 1) = k(n + 1).
So let's have a go.
T(n+1) = T(N+1-1) + K.
T(n+1) = T(n) + K
Assume that T(n) = nk.
T(n+1) = nk + k
T(n+1) = k(n + 1).
And there is your proof, by induction, that T(n) = nk.
That is about as mathematical as you're gonna get on SO.
Nice simple recurrence relation that describes it quite well there.
After your edit I make another solution;)
var n = 5, y = 7;
for (var i = 1; i<=y; i++) {
var offset = ( i*y - (i-1)*n ) % y;
var result = 0;
if (offset === n) {
result = y;
} else {
result = (n - offset) > 0 ? n - offset : offset;
}
console.log(result);
}
[5, 3, 1, 6, 4, 2, 7] in output.
JSFIDDLE: http://jsfiddle.net/mcrLQ/4/
function get(x, A, B) {
var r = (x * A) % B;
return r ? r : B;
}
var A = 5;
var B = 7;
var C = [];
for (var x = 1; x <= B; ++x) {
C.push(get(x, A, B));
}
console.log(C);
Result: [5, 3, 1, 6, 4, 2, 7]
http://jsfiddle.net/xRFTD/
var data = "12345 67123 45671 23456 71234 56712 34567";
var x = 5;
var y = 7;
var results = [];
var i = x - 1; // enumeration in string starts from zero
while ( i <= data.length){
results.push(data[i]);
i = i + x + 1;// +1 for spaces ignoring
}

Operation on an array returns NaN if array length is 1

Player.prototype.d2 = function(ratingList, rdList) {
var tempSum = 0;
for (var i = 0; i < ratingList.length; i++) {
var tempE = this.e(ratingList[i], rdList[i]);
tempSum += Math.pow(this.g(rdList[1]), 2) * tempE * (1 - tempE);
}
return 1 / Math.pow(q, 2) * tempSum;
};
This seems to be the bit in question.
Everything seems fine unless ratingList, rdList and outcomeList only contain one value. Then stuff gets set to NaN instead. I've tried changing the index to -1, changing the comparison to ratingList.length - 1, even tried it with a decrementing for loop, but it always seems to return NaN if the arrays contain only one value.
Is there any way (I'm sure there is -- I guess the question is how) to do away with the for loop and replace it with Array.map() or zip or any composition of those kinds of functions?
You can see ALL of the code here -- it's about 60 LOC
In d2 function you have this line in for loop:
tempSum += Math.pow(this.g(rdList[1]), 2) * tempE * (1 - tempE);
So it is assumed that rdList is 2 elements at least, but you have only one for bob.
Maybe it have to be rdList[i]?

Categories