Why my loop code have different behaviour i++, ++i , i+1 - javascript

Here how it should work
const myArr =[6,8,10,5];
function weSort(arr){
let done = false;
while(!done){
done = true;
for(let i = 0; i < arr.length; i++){
if(arr[i]>arr[i+1]){
done = false;
[arr[i],arr[i+1]] = [arr[i+1],arr[i]]
}
}
}
return arr
}
console.log(weSort(myArr))
But if i change the i+1 to i++ it doesn't do anything because i++ is also 0.i++ is post increment which means it will increment right after it done executing (CMIIW)
const myArr =[6,8,10,5];
function weSort(arr){
let done = false;
while(!done){
done = true;
for(let i = 0; i < arr.length; i++){
if(arr[i]>arr[i++]){
done = false;
[arr[i],arr[i++]] = [arr[i++],arr[i]]
}
}
}
return arr
}
console.log(weSort(myArr))
But if i change the i++ to ++i shouldn't it work like the i+1 since ++i is pre-increment which will add first before got put inside [i]. So shouldn't it look like this?
let i = 0
arr[i]>arr[++i] === arr[0]>arr[1]
Like this code below (Note This Code cause infinite loop)
const myArr =[6,8,10,5];
function weSort(arr){
let done = false;
while(!done){
done = true;
for(let i = 0; i < arr.length; i++){
if(arr[i]>arr[++i]){
done = false;
[arr[i],arr[++i]] = [arr[++i],arr[i]]
}
}
}
return arr
}
console.log(weSort(myArr))
Why it works differently than the first code snippet with i+1?
and cause loop
if something not clear feel free to comment to ask for further info.
I'm sorry for the bad grammar English is not my native i try to explain the best i could.
Thank you.

i + 1 will do the calculation and return the result, leaving i untouched
i++ will return the value of i, then increment i (do i = i + 1)
++i will increment i (i = i + 1), then return its value.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#arithmetic_operators

The reason is that both i++ and ++i and are self assigning. Both the expressions modify the value of the variable i.
In your first snippet, the i + 1 does not modify the value of i - but only generates a new value by adding 1 to the current value of i.
No modification to the loop variable is done there - therefore the loop is not affected.

i++ (or ++i) should only be written one time. That increments the value. only do that once.
I think you want to avoid: arr[i]>arr[++i]
because now you are additionally incrementing i every time that check happens, which logically doesn't really make sense.

Related

Remove duplicates from an array in Javascript (without modify the array) - Understand the logic behind

I started using a website called leetcode and one question is to remove all the duplicates in an array without create a new one. Here is the question https://leetcode.com/problems/remove-duplicates-from-sorted-array/description/
My solution was to loop and the check each element against the next one, then if match use splice to remove the duplicated one. it works but not when you have something like [1,1,1,1,1] or [1,1,2,2,2,2,3,3] so I found on github a working code:
var removeDuplicates = function(nums) {
var i = 0;
for (var n in nums)
if (i === 0 || nums[n] > nums[i-1])
nums[i++] = nums[n];
return i;
};
This code works and passes all the 160 tests, but I don't understand clearly what is doing, especially the part in nums[i++] = nums[n]; can someone be so kind to help me to understand what this, simple, code is doing? thanks
Consider this code that creates a new array:
function removeDuplicates(nums) {
var res = [];
var i = 0;
for (var j=0; j<nums.length; j++)
if (i === 0 || nums[j] !== res[i-1])
res[i++] = nums[j];
return res;
}
The line you're asking about assigns nums[j] as new element at res[i] when the value is not the same as the previous one (res[i-1]), then increments i to put the next non-duplicate value in the next position.
Now we use the same algorithm but instead of assigning to a new res array, we modify the original nums array:
function removeDuplicates(nums) {
var i = 0;
for (var j=0; j<nums.length; j++)
if (i === 0 || nums[j] !== nums[i-1])
nums[i++] = nums[j];
nums.length = i; // drop the rest
}
Given that j >= i is guaranteed, we only modify array elements that we've always visited, so there's no harm in writing on the same array that we are reading from.

Getting 'undefined', can't figure out why

Working my way through 'Eloquent Javascript' and I'm hitting a bit of a roadblock in understanding how to properly use if with for statements in the language. I'm supposed to write a function that counts all instances of the uppercase 'B' in a given string. The code I've written thus far:
function countBs(s) {
var counter = 0;
for (i = 0; i < s.length; i++) {
if ('B' == s.charAt(i)) {}
counter += 1;
}
}
console.log(countBs("BBC"));
expected output: 2
actual output: undefined
Is my loop going wrong, or my 'if'?
You have two bugs
You are incrementing your counter outside of the if statement.
You have no return statement.
The following can be used:
function countBs(s){
var counter = 0;
for(i = 0; i < s.length; i++){
if ('B' == s.charAt(i)) {
counter += 1; // this needs to be inside the if statement
}
}
return counter;
}
Your function does not have a return statement.
A few issues.
function countBs(s) {
var counter = 0;
for (i = 0; i < s.length; i++) {
if ('B' == s.charAt(i)) {
++counter;
}
}
return counter;
}
document.write(countBs("BBC"));
You were not returning counter at the end of the function
Your if statement was opened, then immediately closed, so nothing happens if the character was B
Even if you returned counter and fixed the above 2 errors, the function still would have exited after 1 B was found. To fix this, move the return after the for ends.
If you're interested, the same problem can be solved with this one-liner:
function countBs(s) {
return s.match(/B/g).length;
}
document.write(countBs("BBC"));
Which finds all B characters (case-sensitive), puts them into an array, then returns how many items are in that array.

Javascript - Project Euler Solution 8, code not working properly

I'm a beginning programmer, and am trying to solve Project Euler Problem 8 (finding the thirteen adjacent digits with the greatest product). Here is my code:
var n = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
function multiplyNext13(a){
var result = 1;
for (i = a; i < a + 13; i++){
result *= Number(n[i]);
}
return result;
}
function getAnswer(){
var answer = 5000940;
for (i = 0; i < 988; i++){
if (multiplyNext13(i) > answer){
answer = multiplyNext13(i);
}
}
document.getElementById("a").innerHTML = answer;
}
The function getAnswer() keeps giving me answer = 0, but I don't know what's wrong. I tested the function multiplyNext13() and I believe it's working properly.
What's wrong with this code? Why isn't it working?
You have only one variable i in your whole program, because you failed to declare it with var.
This means each time you enter the loop in multiplyNext13 you also advance the loop in getAnswer.
This also means the value you set in answer = multiplyNext13(i); isn't the same that the one you just computed in if (multiplyNext13(i) > answer){ (note that this double computation also makes your code slower).
Change
for (i = a; i < a + 13; i++){
to
for (var i = a; i < a + 13; i++){
(and of course the same for the other loop).
Once I fix that, I get this result : 23514624000
Demonstration

How to modify a function parameter at the same time new vars are created on a loop?

This is the code without any attempt to add var nn = 99 to the loop
//note that the 'i' is a parameter of the function
function myFunction(arr, i) {
for (i = i ? i + 5 : 1; i < arr.length; i++) {
//...
}
}
When I try to add a new var it do things I don't want:
Edit: it seems this is wrong
for (var nn = 99, i = i ? i + 5 : 1; i < arr.length; i++)
//created a new 'i'
or
for (i = i ? i + 5 : 1, var nn = 99; i < arr.length; i++)
//doesn't work :(
I know it is exactly the same if I move it outside. But one of the things I hate most, is to not be able to understand what I meant when reading a old code after some months. Moving that line inside the loop will make me understand that line easier.
You can't modify the function's parameter. As i is a primitive value (number), JavaScript will call-by-value, not by-reference.
And as you name your second argument "i", it will be available as a local variable from start on. Using the var keyword with "i" somewhere won't change anything.
((i = i ? i + 5 : 1) * 0) + 99
This will always equal 99. But that does not matter, since it is still unclear what you are trying to accomplish.
If your goal is to loop through an array from a designated start spot then you can do this.
for (; i<arr.length; i++) {}
If you can't guarantee that i is a number, then you will have to perform some sort of checking.
for (var index=(i?i:0); index < arr.length; index++) {}
Javascript will pass primitives by value, so you cannot modify the source value from inside this function. You can return the modified value if want.
ivar = func(arr, ivar);
function func(arr, i){
for (;i<arr.length; i++) {}
return i;
}

calculating average using for loop in javascript

function averageCalculator (numvalues) {
for(i=0, i <= numvalues, i++>) {
var score = prompt("input the score")
result1 += score;
}
alert(result1 / 3);
}
this function is later triggered by a button with onclick="averageCalculator (2)
<input type="button" value="Click for the average" onclick="averageCalculator (2)">
any ideas why its not working? it should prompt you for 2 values and then alert you with the average. not sure whats wrong.
Your code has multiple issues. The for loop is not well formatted and you need to terminate statements with a semi-colon. Also you need to declare variables. And your loop will run numvalues+1 times which is why i removed the = in your loop. Also if you want to calculate an average you want to divide by numvalues.
function averageCalculator (numvalues) {
var result1 = 0;
for(i=0; i < numvalues; i++) {
var score = prompt("input the score");
result1 += score;
}
alert(result1 / numvalues);
}
On top of the invalid syntax you will run into a common "problem" with javascript here. The inputs are treated as strings and instead of being added they will be concatenated. Providing 2 and 2 as scores will result in 11. 2 concatenated with 2 = 22 / 2 = 11. You need to cast the value to a number explicitly before adding them together:
function averageCalculator (numvalues) {
var result1 = 0;
for(i=0; i < numvalues; i++) {
var score = prompt("input the score");
result1 += Number(score);
}
alert(result1 / numvalues);
}
Above code will correctly return 2
The syntax of your for-loop is wrong:
for(i=0, i <= numvalues, i++>) {
should be
for(i=0; i <= numvalues; i++) {
Tip: Also, it's better to use
for(var i=0; i <= numvalues; i++) {
since then i will be a local variable instead of a global one.
Try like this
for(var i=0; i <= numvalues; i++){}
An alternative solution (using a functional programming libary, like Underscore.js):
function averageCalculator(numValues) {
var numbers = _.map(_.range(numValues), function(element) {
return +prompt('input the score');
});
var result = _.reduce(numbers, function(memo, number) {
return memo + number;
}, memo);
alert(result / 3);
}
While a little bit more complicated (and less efficient), you'll get rid of loops altogether.
EDIT
The +prompt('input the score') does effectivly the same as Number(prompt('input the score')).

Categories

Resources