Project Euler Largest Prime Factor bug in Javascript - javascript

I am new to javascript and struggling mightily to understand why this doesn't work.
function largestPrimeFactor(num) {
var primeFactors = [];
for (var i = 2; i < num; i++) {
// check if iter i is prime
if (checkIfPrime(i)) {
// if so, see if its a factor of num
while (num % i === 0) {
num /= i;
primeFactors.push(i);
console.log(primeFactors);
console.log(num);
}
}
if (num === 1) {
// return Math.max.apply(Math, primeFactors)
console.log(primeFactors);
console.log(Math.max.apply(Math, primeFactors));
}
}
}
function checkIfPrime(num) {
for (var i = 2; i < num; i++) {
if (num % i === 0) {
return false;
}
}
return true;
}
console.log(largestPrimeFactor(13195));
The final console.log never goes off for the last prime number 29. I never enter the last if(num === 1) case either, which I also don't know why...
When I iterate up to 29, checkIfPrime(i) should be true, and then after 29 / 29 sets num to 1, the last if case should work too.
Why is this not working??
Second Q - is
return Math.max.apply(Math, primeFactors)
the right way to return the max value from an array of integers?
Thanks!

for(var i = 2; i < num; i++) { // line 3
So if num is 29, i can only go to 28. Should change the < to <=.

Related

Find the next greater prime of a given number

Here's the code i wrote to solve the problem:
let isPrime = function(n) {
for (let i = 2; i < n; i++) {
if (n % i === 0) {
return false;
}
}
return true;
};
function nextPrime(num) {
let newNum = num;
for (let i = 0; i < newNum; i++) {
if (!isPrime(newNum)) {
newNum += 1;
} else if (isPrime(newNum)) {
return newNum;
}
}
};
My plan is:
// increment the num by 1 and check if that new num is prime;
// if not, increment again and check again. Repeat the process untill prime is found.
Input and (expected output is commented):
console.log(nextPrime(2)); // 3
console.log(nextPrime(3)); // 5
console.log(nextPrime(7)); // 11
console.log(nextPrime(8)); // 11
console.log(nextPrime(20)); // 23
console.log(nextPrime(97)); // 101
The output i'm getting;
2
3
7
11
23
97
I'd like to know where exactly my implementation is wrong. Also, i'd like the code to be without fancy methods because i'm new to all this. Thank you!
The assignment newNum = num precisely does not make newNum a new number, but the same ! This is why the function returns immediately when the input argument is prime.
By the way, the loop would be much cleaner as
do
{
newNum += 1;
} while (!isPrime(newNum));
function nextPrime(previousPrime) {
const value = previousPrime;
if (value > 2) {
var i, q;
do {
i = 3;
value += 2;
q = Math.floor(Math.sqrt(value));
while (i <= q && value % i) {
i += 2;
}
} while (i <= q);
return value;
}
return value === 2 ? 3 : 2;
}

How to refactor IF statements into ternary operators in javascript?

Hello I am trying to refactor my function but it doesn't seem to be working properly. It works fine normally which is the commented code. Am I writing this wrong or is there a fundamental flaw in my code?
function isPrime(num) {
// if (num <= 1){
// return false
// } else {
// for(var i = 2; i < num; i++){
// if(num % i === 0) return false;
// }
// }
num <= 1 ? false : {
for(let i = 2; i < num; i++){
num % 1 === 0 ? false
}}
return true;
}
Thanks
As far as I can tell, no language having the ternary operator allows running a block of statements, which is what you are doing. The ternary operator is a shorthand version of:
let result;
if (<condition>)
result = resultTrue;
else
result = resultFalse;
Unless JavaScript stabs be in the back on this one, for is a statement that doesn't return anything, and therefore cannot be used the way you want.
The best you could do, I guess, would be:
function isPrime(num) {
if (num <= 1) {
return false;
}
for(var i = 2; i < num; i++) {
if(num % i === 0) return false;
}
}
The else part omitted since hitting the line after the if necessarily means that the condition for it was not met.
Technically what you have can be brought to life with an IIFE:
function isPrime(num) {
return num <= 1 ? false :
(n => {
for (let i = 2; i < n; i++) {
if (n % i === 0) return false;
}
return true;
})(num)
}
for (let i = 0; i < 10; i++) {
console.log(i, isPrime(i));
}
Now it works and there is a ternary operator inside.
Even the attempt without return can be done, just you need isPrime made into an arrow function:
let isPrime = num => num <= 1 ? false :
(n => {
for (let i = 2; i < n; i++) {
if (n % i === 0) return false;
}
return true;
})(num);
for (let i = 0; i < 10; i++) {
console.log(i, isPrime(i));
}
Tadaam, the num <= 1 ? false : part is literally there in the first line, without that nasty return.
But realistically this is not how isPrime should be implemented, your very first attempt is the best one so far.
If you want an actual improvement, use the fact that divisors come in pairs. If x is a divisor of num, then num/x is also divisor of num. So if you were looking for all divisors of num, you would find them in pairs as soon as x=num/x=sqrt(num), so it's enough to check numbers between 2 and Math.floor(Math.sqrt(num)), inclusive. As you preferably don't want JS to calculate this number in every iteration (when checking the condition), you could count downwards, so
for (let i = Math.floor(Math.sqrt(num)); i >= 2; i--)

Javascript Function Issues for Prime Numbers

So what I'm trying to do is use a function that prompts to enter a number and then prints all prime numbers up till that number. I have the code as far as I know but I keep getting an error that the bracket following prime(num) is wrong. Not sure what I'm doing wrong here, would appreciate any help.
function p5Bela() {
var num = prompt("Please enter a number: ", "");
for (i = 2; i <= num; i++) {
if (prime(i)==true) {
alert(i);
}
}
prime(num) {
var flag = true;
var d = 2;
while (flag==true && d <= num/2) {
if (num%d == 0) {
flag = false;
}
d++;
}
return flag;
}
}
Simplest Way
function isPrime(num) {
for(var i = 2; i < num; i++)
if(num % i === 0) return false;
return num > 1;
}
With the ES6 syntax:
const isPrime = num => {
for(let i = 2; i < num; i++)
if(num % i === 0) return false;
return num > 1;
}
You can also decrease the complexity of the algorithm from O(n) to O(sqrt(n)) if you run the loop until square root of a number:
const isPrime = num => {
for(let i = 2, s = Math.sqrt(num); i <= s; i++)
if(num % i === 0) return false;
return num > 1;
}

Find the sum of all the primes below two million using java script

I am trying this code
var sum = 0
for (i = 0; i < 2000000; i++) {
function checkIfPrime() {
for (factor = 2; factor < i; factor++) {
if (i % factor = 0) {
sum = sum;
}
else {
sum += factor;
}
}
}
}
document.write(sum);
I am getting this error:
Invalid left-hand side in assignment
Change if(i % factor = 0) to if( i % factor == 0) and remove the function checkIfPrime() inside the for loop.
var sum = 0
for (i = 0; i < 2000000; i++) {
for (factor = 2; factor < i; factor++) {
if (i % factor == 0) {
sum = sum;
}
else {
sum += factor;
}
}
}
document.write(sum);
The function inside the loop is pointless.
it looks like your code outputs wrong result, for example prime numbers below 6 are 2, 3 and 5, their sum is 10, your code outputs 14 in this case.
Here is another code which outputs sum of primes below max value:
var sieve = [], primes = [], sum = 0, max = 5;
for (var i = 2; i <= max; ++i) {
if (!sieve[i]) {
// i has not been marked -- it is prime
sum += i;
for (var j = i << 1; j <= max; j += i) {
sieve[j] = true;
}
}
}
console.log(sum);
credit to How to find prime numbers between 0 - 100?
function sumPrimes(num) {
var sum = 0;
for (var i = 2; i < num; i++) {
if (isPrime(i)) {
sum += i;
console.log(sum);
}
}
return sum;
}
function isPrime(num) {
if (num <= 1) return false;
else if (num <= 3) return true;
else if (num % 2 == 0 || num % 3 == 0) return false;
var i = 5;
while (i * i <= num) {
if (num % i == 0 || num % (i + 2) == 0) return false;
i += 6;
}
return true
}
console.log(sumPrimes(2000000));
Well, I did with 250 otherwise my screen would have frozen. First of you have to single out the prime numbers after placing them inside an empty Array, which I called primeNumbers from 2 to whatever number you want. Then I create a function that would filter the prime numbers and then add them all with a reduce method inside of another variable called sum and return that variable.
var primeNumbers =[];
for(var i = 2; i < 250; i++){
primeNumbers.push(i);
}//for loop
function isPrime(value){
for(var x=2; x< value; x++){
if(value % x===0){
return false;
}
}//for loop
return true;
}//function isPrime to filter
var sum = primeNumbers.filter(isPrime).reduce(function(acc, val) {
return acc + val;
}, 0);
console.log(sum);
when you are using a variable inside the loop you need to declare them. You have two points in this case
i is not declared
factor is not declare
Your if (i % factor = 0) is wrong, as pointed by some people above.
Also, you never call the checkIfPrime() method. I don't why you created them. Also, I improved your checkIfPrime() method. Please call sumOfPrimes() method in the code below and it should work. You can modify it according to your need
function sumOfPrimes()
{
var sum =0;
for (var i = 0; i < 2000000; i++)
{
var temp = Math.sqrt(i);
for (var factor = 2; factor < temp; factor++)
{
if (i % factor === 0)
{
sum += factor;
}
}
}
console.log(sum);
}
Try changing this line if (i % factor = 0) {
to
if (i % factor == 0) {

Trying to find factors of a number in JS

I am just starting JS, and understand the concept of finding a factor. However, this snippet of code is what I have so far. I have the str variable that outputs nothing but the first factor which is 2. I am trying to add each (int) to the str as a list of factors. What's the wrong in below code snippet?
function calculate(num) {
var str = "";
var int = 2;
if (num % int == 0) {
str = str + int;
int++;
} else {
int++;
}
alert(str);
}
calculate(232);
UPDATED ES6 version:
As #gengns suggested in the comments a simpler way to generate the array would be to use the spread operator and the keys method:
const factors = number => [...Array(number + 1).keys()].filter(i=>number % i === 0);
console.log(factors(36)); // [1, 2, 3, 4, 6, 9, 12, 18, 36]
ES6 version:
const factors = number => Array
.from(Array(number + 1), (_, i) => i)
.filter(i => number % i === 0)
console.log(factors(36)); // [1, 2, 3, 4, 6, 9, 12, 18, 36]
https://jsfiddle.net/1bkpq17b/
Array(number) creates an empty array of [number] places
Array.from(arr, (_, i) => i) populates the empty array with values according to position [0,1,2,3,4,5,6,7,8,9]
.filter(i => ...) filters the populated [0,1,2,3,4,5] array to the elements which satisfy the condition of number % i === 0 which leaves only the numbers that are the factors of the original number.
Note that you can go just until Math.floor(number/2) for efficiency purposes if you deal with big numbers (or small).
As an even more performant complement to #the-quodesmith's answer, once you have a factor, you know immediately what its pairing product is:
function getFactors(num) {
const isEven = num % 2 === 0;
const max = Math.sqrt(num);
const inc = isEven ? 1 : 2;
let factors = [1, num];
for (let curFactor = isEven ? 2 : 3; curFactor <= max; curFactor += inc) {
if (num % curFactor !== 0) continue;
factors.push(curFactor);
let compliment = num / curFactor;
if (compliment !== curFactor) factors.push(compliment);
}
return factors;
}
for getFactors(300) this will run the loop only 15 times, as opposed to +-150 for the original.
#Moob's answer is correct. You must use a loop. However, you can speed up the process by determining if each number is even or odd. Odd numbers don't need to be checked against every number like evens do. Odd numbers can be checked against every-other number. Also, we don't need to check past half the given number as nothing above half will work. Excluding 0 and starting with 1:
function calculate(num) {
var half = Math.floor(num / 2), // Ensures a whole number <= num.
str = '1', // 1 will be a part of every solution.
i, j;
// Determine our increment value for the loop and starting point.
num % 2 === 0 ? (i = 2, j = 1) : (i = 3, j = 2);
for (i; i <= half; i += j) {
num % i === 0 ? str += ',' + i : false;
}
str += ',' + num; // Always include the original number.
console.log(str);
}
calculate(232);
http://jsfiddle.net/r8wh715t/
While I understand in your particular case (calculating 232) computation speed isn't a factor (<-- no pun intended), it could be an issue for larger numbers or multiple calculations. I was working on Project Euler problem #12 where I needed this type of function and computation speed was crucial.
function calculate(num) {
var str = "0";
for (var i = 1; i <= num; i++) {
if (num % i == 0) {
str += ',' + i;
}
}
alert(str);
}
calculate(232);
http://jsfiddle.net/67qmt/
Below is an implementation with the time complexity O(sqrt(N)):
function(A) {
var output = [];
for (var i=1; i <= Math.sqrt(A); i++) {
if (A % i === 0) {
output.push(i);
if (i !== Math.sqrt(A)) output.push(A/i);
}
}
if (output.indexOf(A) === -1) output.push(A);
return output;
}
here is a performance friendly version with complexity O(sqrt(N)).
Output is a sorted array without using sort.
var factors = (num) => {
let fac = [], i = 1, ind = 0;
while (i <= Math.floor(Math.sqrt(num))) {
//inserting new elements in the middle using splice
if (num%i === 0) {
fac.splice(ind,0,i);
if (i != num/i) {
fac.splice(-ind,0,num/i);
}
ind++;
}
i++;
}
//swapping first and last elements
let temp = fac[fac.length - 1];
fac[fac.length - 1] = fac[0];
fac[0] = temp;
// nice sorted array of factors
return fac;
};
console.log(factors(100));
Output:
[ 1, 2, 4, 5, 10, 20, 25, 50, 100 ]
This got me an 85% on Codility (Fails on the upperlimit, over a billion).
Reducing the input by half doesn't work well on large numbers as half is still a very large loop. So I used an object to keep track of the number and it's half value, meaning that we can reduce the loop to one quarter as we work from both ends simultaneously.
N=24 becomes: (1&24),(2&12),(3&8),(4&6)
function solution(N) {
const factors = {};
let num = 1;
let finished = false;
while(!finished)
{
if(factors[num] !== undefined)
{
finished = true;
}
else if(Number.isInteger(N/num))
{
factors[num] = 0;
factors[N/num]= 0;
}
num++
}
return Object.keys(factors).length;
}
Using generators in typescript in 2021
function* numberFactorGenerator(number: number): Generator<number> {
let i: number = 0;
while (i <= number) {
if (number % i === 0) {
yield i;
}
i++;
}
}
console.log([...numberFactorGenerator(12)]); // [ 1, 2, 3, 4, 6, 12 ]
function factorialize(num) {
var result = '';
if( num === 0){
return 1;
}else{
var myNum = [];
for(i = 1; i <= num; i++){
myNum.push(i);
result = myNum.reduce(function(pre,cur){
return pre * cur;
});
}
return result;
}
}
factorialize(9);
I came looking for an algorithm for this for use in factoring quadratic equations, meaning I need to consider both positive and negative numbers and factors. The below function does that and returns a list of factor pairs. Fiddle.
function getFactors(n) {
if (n === 0) {return "∞";} // Deal with 0
if (n % 1 !== 0) {return "The input must be an integer.";} // Deal with non-integers
// Check only up to the square root of the absolute value of n
// All factors above that will pair with factors below that
var absval_of_n = Math.abs(n),
sqrt_of_n = Math.sqrt(absval_of_n),
numbers_to_check = [];
for (var i=1; i <= sqrt_of_n; i++) {
numbers_to_check.push(i);
}
// Create an array of factor pairs
var factors = [];
for (var i=0; i <= numbers_to_check.length; i++) {
if (absval_of_n % i === 0) {
// Include both positive and negative factors
if (n>0) {
factors.push([i, absval_of_n/i]);
factors.push([-i, -absval_of_n/i]);
} else {
factors.push([-i, absval_of_n/i]);
factors.push([i, -absval_of_n/i]);
}
}
}
// Test for the console
console.log("FACTORS OF "+n+":\n"+
"There are "+factors.length+" factor pairs.");
for (var i=0; i<factors.length; i++) {
console.log(factors[i]);
}
return factors;
}
getFactors(-26);
function calculate(num){
var str = "0" // initializes a place holder for var str
for(i=2;i<num;i++){
var num2 = num%i;
if(num2 ==0){
str = str +i; // this line joins the factors to the var str
}
}
str1 = str.substr(1) //This removes the initial --var str = "0" at line 2
console.log(str1)
}
calculate(232);
//Output 2482958116
Here's an optimized solution using best practices, proper code style/readability, and returns the results in an ordered array.
function getFactors(num) {
const maxFactorNum = Math.floor(Math.sqrt(num));
const factorArr = [];
let count = 0; //count of factors found < maxFactorNum.
for (let i = 1; i <= maxFactorNum; i++) {
//inserting new elements in the middle using splice
if (num % i === 0) {
factorArr.splice(count, 0, i);
let otherFactor = num / i; //the other factor
if (i != otherFactor) {
//insert these factors in the front of the array
factorArr.splice(-count, 0, otherFactor);
}
count++;
}
}
//swapping first and last elements
let lastIndex = factorArr.length - 1;
let temp = factorArr[lastIndex];
factorArr[lastIndex] = factorArr[0];
factorArr[0] = temp;
return factorArr;
}
console.log(getFactors(100));
console.log(getFactors(240));
console.log(getFactors(600851475143)); //large number used in Project Euler.
I based my answer on the answer written by #Harman
We don't have to loop till end of the given number to find out all the factors. We just have to loop till reaching the given number's squareroot. After that point we, can figure out the rest of the factors by dividing the given number with the already found factors.
There is one special case with this logic. When the given number has a perfect square, then the middle factor is duplicated. The special case is also handled properly in the below code.
const findFactors = function (num) {
const startingFactors = []
const latterFactors = []
const sqrt = Math.sqrt(num)
for (let i = 1; i <= sqrt; i++) {
if (num % i == 0) {
startingFactors.push(i)
latterFactors.push(num / i)
}
}
// edge case (if number has perfect square, then the middle factor is replicated, so remove it)
if (sqrt % 1 == 0) startingFactors.pop()
return startingFactors.concat(latterFactors.reverse())
}
function factorialize(num) {
if(num === 0)
return 1;
var arr = [];
for(var i=1; i<= num; i++){
arr.push(i);
}
num = arr.reduce(function(preVal, curVal){
return preVal * curVal;
});
return num;
}
factorialize(5);

Categories