[infinite loop] - Sum All Primes

Hi everyone,

I’m stuck on the “Sum All Primes” challenge and was wondering if anyone from the community can help see what’s wrong with my code, thanks in advance.

Link to exercise: https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-primes

At this point I’m not even at the stage where I can add up all the prime numbers. All I want to do is create an array of prime numbers that is less than or equal to the “num” that is passed in.

function sumPrimes(num) {

  let arrayOfPrimeNumbers = [2, 3];
  
  let counter = 1;

  // I found a formula on the internet which states that apart from the numbers 2 and 3, the way to find prime numbers is...
  // 6(1) - 1;
  // 6(1) + 1;
  // 6(2) - 1;
  // 6(2) + 1;  etc.
  let formula1 = (6 * counter) - 1;
  let formula2 = (6 * counter) + 1; 

  // I'm saying, while the last value in the array is less than or equal to "num", execute the code.
  while (arrayOfPrimeNumbers[arrayOfPrimeNumbers.length - 1] <= num) {
    if (formula1 <= num) {
      arrayOfPrimeNumbers.push(formula1);
    } else {
      break; // I want to end the "while" loop if it is not the case that formula1 is less than or equal to num.
    }

    if (formula2 <= num) {
      arrayOfPrimeNumbers.push(formula2);
    } else {
      break; // I want to end the "while" loop if it is not the case that formula2 is less than or equal to num.
    }
    
    counter++;    
  }

  console.log(arrayOfPrimeNumbers);
}

sumPrimes(10);

It seems like the code leads to some kind of infinite loop. I’d be most grateful if someone can point me in the right direction, thanks in advance.

Take a closer look at the while loop and the formula1 and formula2 variables. At which point one of the variables changes so it’s not <= num anymore?

2 Likes

@sanity, thanks for the comment, appreciate it.

I’ve looked at the code again and still can’t quite figure out what’s wrong.

This is how I understand the code:

  1. First time around, the “while” loop checks whether the last value of “arrayOfPrimeNumbers” is less than or equal to “num”. Since 3 is less than 10, the code is executed.

  2. We ask, if 6(1) - 1 is less than 10, then push that number in. Since 5 is less than 10, it is pushed into the array, so that the array is now [2, 3, 5].

  3. We then ask, if 6(1) + 1 is less than 10, then push that number in. Since 7 is less than 10, it is pushed into the array, so that the array is now [2, 3, 5, 7].

  4. We add 1 to “counter”, so that it is now 2.

  5. The “while” loop checks the condition again, and the last value in the array is 7, which is less than or equal to 10, so the code is executed.

  6. We check, if 6(2) - 1 is less than 10, then push 11 into the array. This fails, so the else statement is executed. We say, break out of the loop, and at this point the “while” loop should end.

  7. We console log “arrayOfPrimeNumbers”.

I would be most grateful if you could take another look to see whether I’m understanding the code correctly, and if not, where I’m going wrong. I’m not so familiar with using “break” but from what I see online (like from MDN and other websites), it seems that I should be using it correctly. Thanks in advance.

This is not exactly correct.

4*6 = 24

23 is prime but 25 is not.

You still need a way to verify which numbers are prime or not.


Your loop is infinite because you never change the values stored in these variables

So this never happens

Instead you use the same values for formula1 and formula2 again

1 Like

@JeremyLT, hey thanks for your help.

I didn’t realize the formulas weren’t foolproof ways of finding prime numbers. Now that you’ve pointed that out, it seems I need to change the “if” statement to something like:

if (formula1 <= num && formula1 % 5 !== 0)

But if I assume the formulas are correct (simply for the purposes of understanding why an infinite loop is occurring), I don’t quite understand this:

I would have thought “counter” would get updated via “counter++”, and as such, the variable “formula1” would store different values every time “counter” is updated. I can’t quite get my head around why this doesn’t work, I’d be most grateful for any help.

I also updated my code so I have:

function sumPrimes(num) {

  let arrayOfPrimeNumbers = [2, 3];
  
  let counter = 1;
  let formula1 = (6 * counter) - 1;
  let formula2 = (6 * counter) + 1; 

  while (arrayOfPrimeNumbers[arrayOfPrimeNumbers.length - 1] <= num) {
    if (formula1 <= num) {
      formula1 = (6 * counter) - 1; // Really don't understand why I need this again
      arrayOfPrimeNumbers.push(formula1);
    } else {
      break;
    }

    if (formula2 <= num) {
      formula2 = (6 * counter) + 1; // Really don't understand why I need this again
      arrayOfPrimeNumbers.push(formula2);
    } else {
      break;
    }
    
    counter++;    
  }

  console.log(arrayOfPrimeNumbers);
}

sumPrimes(20); // Array(10) [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 25 ]

When I call “sumPrimes(20)”, I see that the values 23 and 25 are added to the array, which doesn’t seem to make sense since these values are not less than “num” (i.e., 20).

Also interesting is if I change the placement of both formulas, like:

function sumPrimes(num) {

  let arrayOfPrimeNumbers = [2, 3];
  
  let counter = 1;
  let formula1 = (6 * counter) - 1;
  let formula2 = (6 * counter) + 1; 

  while (arrayOfPrimeNumbers[arrayOfPrimeNumbers.length - 1] <= num) {
    if (formula1 <= num) {
      arrayOfPrimeNumbers.push(formula1);
      formula1 = (6 * counter) - 1; // changed the placement of the formula
    } else {
      break;
    }

    if (formula2 <= num) {
      arrayOfPrimeNumbers.push(formula2);
      formula2 = (6 * counter) + 1; // changed the placement of the formula
    } else {
      break;
    }
    
    counter++;    
  }

  console.log(arrayOfPrimeNumbers);
}

sumPrimes(20); // Array(10) [ 2, 3, 5, 7, 5, 7, 11, 13, 17, 19 ]

The funny thing is 5 and 7 are repeated.

Lastly, sorry about the length of this post, if I change the “if” statements to make sure 25 is not added to the array (I know this is not a solution for making sure the number is prime, but I wanted to see what would happen):

function sumPrimes(num) {

  let arrayOfPrimeNumbers = [2, 3];
  
  let counter = 1;
  let formula1 = (6 * counter) - 1;
  let formula2 = (6 * counter) + 1; 

  while (arrayOfPrimeNumbers[arrayOfPrimeNumbers.length - 1] <= num) {
    if (formula1 <= num && formula1 % 5 != 0) { // Changed the code here
      arrayOfPrimeNumbers.push(formula1);
      formula1 = (6 * counter) - 1;
    } else {
      break;
    }

    if (formula2 <= num && formula1 % 5 != 0) {
      arrayOfPrimeNumbers.push(formula2); // Changed so that 25 won't be added
      formula2 = (6 * counter) + 1;
    } else {
      break;
    }
    
    counter++;    
  }

  console.log(arrayOfPrimeNumbers);
}

sumPrimes(20); // Array [ 2, 3 ]

I end up with an array of only [2, 3], which I don’t understand.

Again, sorry about the length of this post, any addition help would be greatly appreciated, thanks.

counter is updated, but lines assiging to formula1 and formula2 are executed just once, using whatever value counter has at that time. These are not getting updated every time counter changes.

As you have noticed, moving the assignment to the while loop will change the values. That’s because lines within loop are executed again and again. Declaration of formula1 and formula2 could be just at the start of loop, they don’t need to be declared before that, and depending the change on the if statements is not needed here.

1 Like

@sanity, thanks so much for your help!

This is what I have trouble understanding. If you have a moment, I was wondering if you could talk a little bit more about why one variable declared outside the loop (in this case “counter”) gets updated, but not the other variables (“formula1” and “formula2”). It seems a bit arbitrary. I would be most grateful for any help.

Also, I’ve rejigged the code and now it does as intended, notwithstanding the fact that the formulas actually come up with some false primes like 25, and 49, as @JeremyLT pointed out earlier.

So here’s the new code:

function sumPrimes(num) {

  let arrayOfPrimeNumbers = [2, 3];
  let counter = 1;
  
  while (arrayOfPrimeNumbers[arrayOfPrimeNumbers.length - 1] <= num) {
    let formula1 = (6 * counter) - 1;
    let formula2 = (6 * counter) + 1; 

    if (formula1 <= num) {
      arrayOfPrimeNumbers.push(formula1);
    } else {
      break;
    }

    if (formula2 <= num) {
      arrayOfPrimeNumbers.push(formula2);
    } else {
      break;
    }
    
    counter++;    
  }

  console.log(arrayOfPrimeNumbers);
}

sumPrimes(30); // Array(11) [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 25, 29 ]

But just out of curiosity I wanted to take out all the numbers divisive by 5. I’ve tried changing the code to this:

function sumPrimes(num) {

  let arrayOfPrimeNumbers = [2, 3, 5, 7]; // Tweaked
  let counter = 1;
  
  while (arrayOfPrimeNumbers[arrayOfPrimeNumbers.length - 1] <= num) {
    let formula1 = (6 * counter) - 1;
    let formula2 = (6 * counter) + 1; 

    // Tweaked
    if (formula1 <= num && formula1 % 5 !== 0) {
      arrayOfPrimeNumbers.push(formula1);
    } else {
      break;
    }

    // Tweaked
    if (formula2 <= num && formula2 % 5 !== 0) {
      arrayOfPrimeNumbers.push(formula2);
    } else {
      break;
    }
    
    counter++;    
  }

  console.log(arrayOfPrimeNumbers);
}

sumPrimes(30); // Array(4) [ 2, 3, 5, 7 ]

Would you be able to also shed some light on why this way of removing elements divisible by 5 doesn’t work? (note that I changed the starting array to [2, 3, 5, 7] as I was trying to keep 5 in the array but remove 25, but turns out the array simply stops at 7). I understand this isn’t a solution to finding prime numbers, but I’m stumped as to why this far-from-perfect approach doesn’t work as intended, even in that limited way.

Sorry about the length of this post and thanks in advance. I’d be most grateful for any help.

There’s difference that counter was being changed within the loop since the beginning - with the counter++.

For the question with 25, take a look at this if statement:

    if (formula1 <= num && formula1 % 5 !== 0) {
      arrayOfPrimeNumbers.push(formula1);
    } else {
      break;
    }

formula1 will be pushed to the array if both formula1 is lower or equal num and if formula1 % 5 is not 0.
Otherwise loop is broken. That means, when formula1 <= num is false loop is broken, or when formula1 % 5 !== 0 is false.

Starting with counter === 1 first formula1 === 5. For which 5 % 5 !== 0 is false and loop is broken.

1 Like

You cannot fix this with a simple single extra condition. You need to check if any number less than formula1 (or formula2) divides evenly into it

1 Like

@sanity and @JeremyLT, thanks for the responses, appreciate it.

This makes sense now, it’s the fact that “counter” is being changed within the loop that makes it different from “formula1” and “formula2”, which simply appeared outside the loop in the earlier version of the code. Thanks for clarifying this.

Regarding this:

Ahhh, I get it now. I thought by starting the array “arrayOfPrimeNumbers” with [2, 3, 5, 7], it would push 11, 13, etc., into the array, but not 25.

But the “if” statement is actually testing “if 6(1) - 1 <= num && there’s no remainder when divided by 5” and since the first number is 5, the loop breaks. I don’t know why I thought starting the array off with [2, 3, 5, 7] would make a difference :flushed:, I don’t know what to say… I shouldn’t have made this mistake… Thanks for clarifying, really appreciate your help.

Regarding:

This is helpful, it gives me a new way of looking at the problem, as always, thanks for your help.

2 Likes

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.