Related
I am trying to solve the Fibonacci algorithm using matrices. My target time complexity is an o(logn) instead of an o(n). The return output of the program is not the number for the series but the sixth significant digits. Its why I am returning the remainder of the solution divided by a million.
I have written the code and it runs well but I noticed that for extremely large inputs, I get a NAN(not a number) instead of an output
const fib = (n) => {
let fibMatrix = [[1,1], [1,0]]
if(n == 0){
return 0;
}
raiseToPower(fibMatrix, n - 1);
return Math.floor(fibMatrix[0][0] % 1000000)
}
const raiseToPower = (matrix, n) => {
if(n == 0 || n == 1){
return;
}
let newMatrix = [[1,1], [1,0]]
raiseToPower(matrix, Math.floor(n / 2))
multiplyMatrices(matrix, matrix)
if(n % 2 !== 0){
multiplyMatrices(matrix, newMatrix)
}
}
const multiplyMatrices = (matrix, newMatrix) => {
let x = matrix[0][0]*newMatrix[0][0] + matrix[0][1]*newMatrix[1][0];
let y = matrix[0][0]*newMatrix[0][1] + matrix[0][1]*newMatrix[1][1];
let z = matrix[1][0]*newMatrix[0][0] + matrix[1][1]*newMatrix[1][0];
let w = matrix[1][0]*newMatrix[0][1] + matrix[1][1]*newMatrix[1][1];
matrix[0][0] = x;
matrix[0][1] = y;
matrix[1][0] = z;
matrix[1][1] = w;
}
console.log(fib(2000))
Thats my code above. Is there anything I could change to actually make this much more performant?
I actually found the error. My numbers were getting larger than the maximum value.
I changed this by instead returning the remainder of my value divided by a million to the matrix and then returning the value from the matrix instead of returning the value and then dividing by a million. The former is efficient and works for any sized inputs.
const fib = (n) => {
let fibMatrix = [[1,1], [1,0]]
if(n == 0){
return 0;
}
raiseToPower(fibMatrix, n - 1);
return (fibMatrix[0][0])
}
const raiseToPower = (matrix, n) => {
if(n == 0 || n == 1){
return;
}
let newMatrix = [[1,1], [1,0]]
raiseToPower(matrix, Math.floor(n / 2))
multiplyMatrices(matrix, matrix)
if(n % 2 !== 0){
multiplyMatrices(matrix, newMatrix)
}
}
const multiplyMatrices = (matrix, newMatrix) => {
let x = (matrix[0][0]*newMatrix[0][0] + matrix[0][1]*newMatrix[1][0]);
let y = (matrix[0][0]*newMatrix[0][1] + matrix[0][1]*newMatrix[1][1]);
let z = (matrix[1][0]*newMatrix[0][0] + matrix[1][1]*newMatrix[1][0]);
let w = (matrix[1][0]*newMatrix[0][1] + matrix[1][1]*newMatrix[1][1]);
matrix[0][0] = x % 1000000;
matrix[0][1] = y % 1000000;
matrix[1][0] = z % 1000000;
matrix[1][1] = w % 1000000;
}
console.log(fib(10000))
I'm generating a number based on a fixed character set.
function generator()
{
var text = "";
var char_list = "LEDGJR", number_list = "0123456789";
for(var i=0; i < 2; i++ )
{
text += char_list.charAt(Math.floor(Math.random() * char_list.length));
}
for(var j=0; j < 2; j++ )
{
text += number_list.charAt(Math.floor(Math.random() *
number_list.length));
}
return text;
}
Result :
RE39, JE12 etc...
Once all the permutation related to the above sequence is done, then the generator should generate string as RE391, JE125 means adding one more number to the complete number.
How can I get the permutation count of sequence?
For simplicity consider the case where:
chars = "AB"
nums = "123";
and we want to generate a 4-digit sequence of two chars and two numbers.
We define these variables
rows = [chars, chars, nums, nums]
rowSizes = rows.map(row => row.length) // [2, 2, 3, 3]
It’s easy to see the set size of all possible permuations equals:
spaceSize = rowSizes.reduce((m, n) => m * n, 1) // 2*2*3*3 = 36
And we define two set of utility functions, usage of which I'll explain in detail later.
decodeIndex() which gives us uniqueness
function euclideanDivision(a, b) {
const remainder = a % b;
const quotient = (a - remainder) / b;
return [quotient, remainder]
}
function decodeIndex(index, rowSizes) {
const rowIndexes = []
let dividend = index
for (let i = 0; i < rowSizes.length; i++) {
const [quotient, remainder] = euclideanDivision(dividend, rowSizes[i])
rowIndexes[i] = remainder
dividend = quotient
}
return rowIndexes
}
getNextIndex() which gives us pseudo-randomness
function isPrime(n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (let i = 5; i * i <= n; i = i + 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return true;
}
function findNextPrime(n) {
if (n <= 1) return 2;
let prime = n;
while (true) {
prime++;
if (isPrime(prime)) return prime;
}
}
function getIndexGeneratorParams(spaceSize) {
const N = spaceSize;
const Q = findNextPrime(Math.floor(2 * N / (1 + Math.sqrt(5))))
const firstIndex = Math.floor(Math.random() * spaceSize);
return [firstIndex, N, Q]
}
function getNextIndex(prevIndex, N, Q) {
return (prevIndex + Q) % N
}
Uniqueness
Like mentioned above, spaceSize is the number of all possible permutations, thus each index in range(0, spaceSize) uniquely maps to one permutation. decodeIndex helps with this mapping, you can get the corresponding permutation to an index by:
function getSequenceAtIndex(index) {
const tuple = decodeIndex(index, rowSizes)
return rows.map((row, i) => row[tuple[i]]).join('')
}
Pseudo-Randomness
(Credit to this question. I just port that code into JS.)
We get pseudo-randomness by polling a "full cycle iterator"†. The idea is simple:
have the indexes 0..35 layout in a circle, denote upperbound as N=36
decide a step size, denoted as Q (Q=23 in this case) given by this formula‡
Q = findNextPrime(Math.floor(2 * N / (1 + Math.sqrt(5))))
randomly decide a starting point, e.g. number 5
start generating seemingly random nextIndex from prevIndex, by
nextIndex = (prevIndex + Q) % N
So if we put 5 in we get (5 + 23) % 36 == 28. Put 28 in we get (28 + 23) % 36 == 15.
This process will go through every number in circle (jump back and forth among points on the circle), it will pick each number only once, without repeating. When we get back to our starting point 5, we know we've reach the end.
†: I'm not sure about this term, just quoting from this answer
‡: This formula only gives a nice step size that will make things look more "random", the only requirement for Q is it must be coprime to N
Full Solution
Now let's put all the pieces together. Run the snippet to see result.
I've also includes the a counter before each log. For your case with char_list="LEDGJR", number_list="0123456789", the spaceSize for 4-digit sequence should be 6*6*10*10 = 3600
You'll observe the log bump to 5-digit sequence at 3601 😉
function euclideanDivision(a, b) {
const remainder = a % b;
const quotient = (a - remainder) / b;
return [quotient, remainder];
}
function decodeIndex(index, rowSizes) {
const rowIndexes = [];
let divident = index;
for (let i = 0; i < rowSizes.length; i++) {
const [quotient, remainder] = euclideanDivision(divident, rowSizes[i]);
rowIndexes[i] = remainder;
divident = quotient;
}
return rowIndexes;
}
function isPrime(n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (let i = 5; i * i <= n; i = i + 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return true;
}
function findNextPrime(n) {
if (n <= 1) return 2;
let prime = n;
while (true) {
prime++;
if (isPrime(prime)) return prime;
}
}
function getIndexGeneratorParams(spaceSize) {
const N = spaceSize;
const Q = findNextPrime(Math.floor((2 * N) / (1 + Math.sqrt(5))));
const firstIndex = Math.floor(Math.random() * spaceSize);
return [firstIndex, N, Q];
}
function getNextIndex(prevIndex, N, Q) {
return (prevIndex + Q) % N;
}
function generatorFactory(rows) {
const rowSizes = rows.map((row) => row.length);
function getSequenceAtIndex(index) {
const tuple = decodeIndex(index, rowSizes);
return rows.map((row, i) => row[tuple[i]]).join("");
}
const spaceSize = rowSizes.reduce((m, n) => m * n, 1);
const [firstIndex, N, Q] = getIndexGeneratorParams(spaceSize);
let currentIndex = firstIndex;
let exhausted = false;
function generator() {
if (exhausted) return null;
const sequence = getSequenceAtIndex(currentIndex);
currentIndex = getNextIndex(currentIndex, N, Q);
if (currentIndex === firstIndex) exhausted = true;
return sequence;
}
return generator;
}
function getRows(chars, nums, rowsOfChars, rowsOfNums) {
const rows = [];
while (rowsOfChars--) {
rows.push(chars);
}
while (rowsOfNums--) {
rows.push(nums);
}
return rows;
}
function autoRenewGeneratorFactory(chars, nums, initRowsOfChars, initRowsOfNums) {
let realGenerator;
let currentRowOfNums = initRowsOfNums;
function createRealGenerator() {
const rows = getRows(chars, nums, initRowsOfChars, currentRowOfNums);
const generator = generatorFactory(rows);
currentRowOfNums++;
return generator;
}
realGenerator = createRealGenerator();
function proxyGenerator() {
const sequence = realGenerator();
if (sequence === null) {
realGenerator = createRealGenerator();
return realGenerator();
} else {
return sequence;
}
}
return proxyGenerator;
}
function main() {
const char_list = "LEDGJR"
const number_list = "0123456789";
const generator = autoRenewGeneratorFactory(char_list, number_list, 2, 2);
let couter = 0
setInterval(() => {
console.log(++couter, generator())
}, 10);
}
main();
I was asked this question in an interview:
An integer is special if it can be expressed as a sum that's a palindrome (the same backwards as forwards). For example, 22 and 121 are both special, because 22 equals 11+11 and 121 equals 29+92.
Given an array of integers, count how many of its elements are special.
but I couldn't think of any solution. How can this be done?
In the stress and the hurry of an interview, I would have certainly found a dumb and naive solution.
pseudo code
loop that array containing the numbers
Looping from nb = 0 to (*the number to test* / 2)
convert nb to string and reverse the order of that string (ie : if you get "29", transform it to "92")
convert back the string to a nb2
if (nb + nb2 == *the number to test*)
this number is special. Store it in the result array
end loop
end loop
print the result array
function IsNumberSpecial(input)
{
for (let nb1 = 0; nb1 <= (input / 2); ++nb1)
{
let nb2 = parseInt(("" + nb1).split("").reverse().join("")); // get the reverse number
if (nb2 + nb1 == input)
{
console.log(nb1 + " + " + nb2 + " = " + input);
return (true);
}
}
return (false);
}
let arr = [22, 121, 42];
let len = arr.length;
let result = 0;
for (let i = 0; i < len; ++i)
{
if (IsNumberSpecial(arr[i]))
++result;
}
console.log(result + " number" + ((result > 1) ? "s" : "") + " found");
Here's a rather naïve solution in pseudocode for determining if a number is 'special':
Given an number N (assumed to be an integer)
Let I = Floor(N / 2)
Let J = Ceil(N / 2)
While (I > 0)
If I is the reverse of J Then
Return True
End
I <- I - 1
J <- J + 1
End
Return False
A quick JS implementation:
function isSpecial(n) {
for (var i = Math.floor(n / 2), j = Math.ceil(n / 2); i > 0; i--, j++) {
console.info(`checking ${i} + ${j}`);
if (i.toString().split('').reverse().join('') === j.toString())
return true;
}
return false;
}
console.log(isSpecial(121));
I'll leave it up to the you implement the function to count the special numbers in the array. This could be made more efficient by improving the rather crude method for checking for string reversals or possibly by more intelligently skipping numbers.
Some pseudo code?
num_special = 0
for item in array:
for num in range(1, total):
if num + int(string(num).reversed()) == item
num_special += 1
break
print(num_special)
EDIT:
Here's a working Python example:
array = [22, 121]
num_special = 0
for item in array:
for num in range(1, item):
if (num + int(str(num)[::-1]) == item):
num_special += 1
break
print(num_special)
https://repl.it/repls/UsedLovelyCategory
Assuming we want two summands - this does not seem to be specified in the question but every answer has assumed it!
(Without this assumption, every number can be written as a reversible sum of 1s.)
Single digit summands:
n is even
Two digit summands:
10x + y + 10y + x
11x + 11y
11(x + y)
n is divisible by 11
Three digit summands:
100x + 10y + z + 100z + 10y + x
101x + 20y + 101z
101(x + z) + 20y
more complex but we can still
do better than a brute force
loop of 1 to n / 2
Etc... (we could probably write a function that generalises and searches over this algebra)
UPDATE
JavaScript code (interestingly, a result for 1111111110 seems to be found faster by the brute force 1 to n/2 loop! Maybe some other optimisations can be made):
function f(n){
let start = new Date;
let numDigits = 0;
let t = Math.ceil(n / 2);
while (t){
numDigits++;
t = ~~(t/10);
}
// Summands split between x and x+1 digits
if (n / 2 + 0.5 == Math.pow(10, numDigits - 1))
return false;
let cs = [];
let l = Math.pow(10, numDigits - 1);
let r = 1;
while (l >= r){
cs.push(l + r);
l /= 10;
r *= 10;
}
let sxs = new Array(cs.length);
const m = cs.length & 1 || 2;
sxs[cs.length-1] = m*cs[cs.length-1];
for (let i=cs.length-2; i>=0; i--)
sxs[i] = 2*cs[i] + sxs[i + 1];
let stack = [[0, n, []]];
let results = [];
while (stack.length){
let [i, curr, vs] = stack.pop();
if (i == cs.length - 1){
let d = curr / cs[i];
if (d == ~~d &&
((cs.length & 1 && d < 10) || ((!(cs.length & 1) || cs.length == 1) && d < 19)))
results.push(vs.concat('x'));
continue;
}
t = 2;
curr -= t*cs[i];
stack.push([
i + 1, curr,
vs.slice().concat(t)]);
while (curr >= sxs[i + 1]){
curr -= cs[i];
stack.push([
i + 1, curr,
vs.slice().concat(++t)]);
}
}
let time = new Date - start;
return [!!results.length, (time) + 'ms', cs, results];
}
let ns = [
22, 121, 42,
66666,
777777,
8888888,
99999999,
68685,
68686]
for (let n of ns)
console.log(n, JSON.stringify(f(n)));
My JS variant:
const reverseInt = (n) =>
parseInt(n.toString().split('').reverse().join(''))
const checkSpecialInt = (n) =>{
for(let i=1;i<=n;i++){
if (i+reverseInt(i)==n) return true;
}
return false;
}
const checkSpecialIntArray = (arr) =>
arr.filter((e,i)=>checkSpecialInt(e)).length;
let test = [122, 121, 22, 21];
console.log(checkSpecialIntArray(test));
The requirement does not includes returning every possible combination of matched "special numbers", only that a match is found.
const isSpecialInteger = arr => {
// `arr`: `Array`
// result, initialized to `0`
let res = 0;
// iterate input `arr`
for (let n of arr) {
// divide `n` by `2`
const c = n / 2;
// check if `n` is an integer or decimal
// if decimal subtract decimal portion of 1st divided decimal
// add decimal portion to 2nd portion of divided decimal
// else set `x`, `y` to even division of input `n`
let [x, y] = !Number.isInteger(c) ? [c - (c % 10), c + (c % 10)] : [c, c];
// set label for `for` loop
// decrement result of `Math.max(x, y)`
N: for (let i = Math.max(x, y); i; i--) {
// check if `i` converted to
// string, then array reveresed
// if equal to `n`
// if `true` increment `res` by `1` `break` `N` loop
if (i + +[...`${i}`].reverse().join`` === n) {
res+= 1;
break N;
}
}
}
// return positive integer or `0`
return res;
}
console.log(
isSpecialInteger([22, 121])
);
Here is one of the brute-force approaches in JAVA and this can be optimised further,
import java.util.Scanner;
public class Solution
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
String str = in.nextLine();
String[] inp = str.split(",");
System.out.println(isSpecial(inp,inp.length));
}
public static int isSpecial(String[] inp, int inpSize)
{
int arr[] = new int[inp.length];
for(int i=0;i<inpSize;i++)
{
arr[i] = Integer.parseInt(inp[i]);
}
int spclCount = 0;
for(int i=0;i<arr.length;i++)
{
for(int j=1;j<((arr[i]/2)+1);j++)
{
if(j+getReverse(j) == arr[i])
{
spclCount++;
break;
}
}
}
return spclCount;
}
public static int getReverse(int n)
{
int rem,rev=0;
while(n != 0)
{
rem = n % 10;
rev = (rev*10) + rem;
n /= 10;
}
return rev;
}
}
Question:
An integer is special if it can be expressed as a sum that's a palindrome (the same backwards as forwards). For example, 22 and 121 are both special, because 22 equals 11+11 and 121 equals 29+92.
Given an array of integers, count how many of its elements are special
My Approach:
public class PalindromicSum {
public static void getSplNumber(int[] arrip) {
//to iterate i/p array
for (int i = 0; i < arrip.length; i++) {
int tempSum = 0;
//to iterate from 1 to number/2
for (int j = 1; j <= arrip[i] / 2; j++) {
//to get the reverse of the number
int revNum = getRevNum(j);
tempSum = revNum + j;
if (tempSum == arrip[i]) {
System.out.println(arrip[i]);
break;
}
}
}
}
public static int getRevNum(int num) {
int rev = 0;
//to get reverse of a number
while(num!=0) {
int reminder = num%10;
rev = rev*10 + reminder;
num = num/10;
}
return rev;
}
public static void main(String[] args) {
int[] arr = { 121, 11, 10, 3, 120, 110};
getSplNumber(arr);
}
}
I was trying to find the prime factors of a number, recorded below as 'integer' using a for loop in javascript. I can't seem to get it working and I'm not sure whether it's my JavaScript or my calculation logic.
//integer is the value for which we are finding prime factors
var integer = 13195;
var primeArray = [];
//find divisors starting with 2
for (i = 2; i < integer/2; i++) {
if (integer % i == 0) {
//check if divisor is prime
for (var j = 2; j <= i / 2; j++) {
if (i % j == 0) {
isPrime = false;
} else {
isPrime = true;
}
}
//if divisor is prime
if (isPrime == true) {
//divide integer by prime factor & factor store in array primeArray
integer /= i
primeArray.push(i);
}
}
}
for (var k = 0; k < primeArray.length; k++) {
console.log(primeArray[k]);
}
The answer above is inefficient with O(N^2) complexity. Here is a better answer with O(N) complexity.
function primeFactors(n) {
const factors = [];
let divisor = 2;
while (n >= 2) {
if (n % divisor == 0) {
factors.push(divisor);
n = n / divisor;
} else {
divisor++;
}
}
return factors;
}
const randomNumber = Math.floor(Math.random() * 10000);
console.log('Prime factors of', randomNumber + ':', primeFactors(randomNumber).join(' '))
You can filter for duplicates as you please!
Here's a working solution:
function getPrimeFactors(integer) {
const primeArray = [];
let isPrime;
// Find divisors starting with 2
for (let i = 2; i <= integer; i++) {
if (integer % i !== 0) continue;
// Check if the divisor is a prime number
for (let j = 2; j <= i / 2; j++) {
isPrime = i % j !== 0;
}
if (!isPrime) continue;
// if the divisor is prime, divide integer with the number and store it in the array
integer /= i
primeArray.push(i);
}
return primeArray;
}
console.log(getPrimeFactors(13195).join(', '));
You were very much on the right track. There were two minor mistakes. The evaluation of integer - 1 seemed to be incorrect. I believe the more appropriate evaluation is <= integer in your outer for loop. This is because when you divide your integer below integer /= i, this results in the final integer evaluation to be 29. The final prime divisor in this case is also 29 and as such will need to be evaluated as <= as oppose to < integer - 1.
As for why the final log statement isn't working, there was a simple typo of primeArray[i] as oppose to primeArray[k].
I do believe there is a mistake in both code above. If you replace the integer by 100 the prime factorization won't work anymore as the factor 2 cannot be considered with those for loops. As j = 2, i = 2 and j<=i/2 in the condition - meaning the loop will never run for i=2, which is a prime factor.
Tried to make it work this way but couldn't figure out.
Had to rely on a different approach with a while loop here :
function getAllFactorsFor(remainder) {
var factors = [], i;
for (i = 2; i <= remainder; i++) {
while ((remainder % i) === 0) {
factors.push(i);
remainder /= i;
}
}
return factors;
}
https://jsfiddle.net/JamesOR/RC7SY/
You could also go with something like that :
let findPrimeFactors = (num) => {
let arr = [];
for ( var i = 2; i < num; i++) {
let isPrime
if (num % i === 0) {
isPrime = true;
for (var j = 2; j <= i; j++) {
if ( i % j === 0) {
isPrime == false;
}
}
}if (isPrime == true) { arr.push(i)}
}console.log(arr)
}
findPrimeFactors(543)
We can find the prime factor numbers up to n with only one loop. It is a very simple solution without any nested loop.
Time complexity would be less than O(n) because we are dividing "n" by "i".
function primeFactors(n) {
let arr=[];
let i = 2;
while(i<=n){
if(n%i == 0) {
n= n/i;
arr.push(i);
} else {
i++;
}
}
return arr;
}
// primeFactors(10) [2,5]
// primeFactors(10) [2,2,5,5]
// primeFactors(2700) [2, 2, 3, 3, 3, 5, 5]
When factorizing an integer (n) to its prime factors, after finding the first prime factor, the problem in hand is reduced to finding prime factorization of quotient (q).
Suppose n is divisible to prime p1 then we have n = p1 * q1 so after finding p1 the problem is reduced to factorizing q1 (quotient). If the function name is primeFactorizer then we can call it recursively and solution for n would be:
n = p1 * primeFactorizer(q1)
n = p1 * p2 * primeFactorizer(q2)
...
Until qn is prime itself.
Also I'm going to use a helper generator function which generates primes for us:
function * primes () {
let n = 2
while (true) {
let isPrime = true
for (let i = 2; i <= n / 2; i++) {
if (n % i === 0) {
isPrime = false
break
}
}
if (isPrime) {
yield n
}
n++
}
}
And function to factorize n would be:
function primeFactorizer (n, result = []) {
for (const p of primes()) {
if (n === p) {
result.push(p)
return result
}
if (n % p === 0) {
result.push(p)
return primeFactorizer(n / p, result)
}
}
}
I've refined this function over time, trying to get it as fast as possible (racing it against others' functions that I've found online, haven't found one that runs consistently faster than it yet).
function primFact(num) {
var factors = [];
/* since 2 is the only even prime, it's easier to factor it out
* separately from the odd factor loop (for loop doesn't need to
* check whether or not to add 1 or 2 to f).
* The condition is essentially checking if the number is even
* (bitwise "&" operator compares the bits of 2 numbers in binary
* and outputs a binary number with 1's where their digits are the
* same and 0's where they differ. In this case it only checks if
* the final digit for num in binary is 1, which would mean the
* number is odd, in which case the output would be 1, which is
* interpreted as true, otherwise the output will be 0, which is
* interpreted as false. "!" returns the opposite boolean, so this
* means that '!(num & 1)' is true when the num is not odd)
*/
while (!(num & 1)) {
factors.push(2);
num /= 2;
}
// 'f*f <= num' is faster than 'f <= Math.sqrt(num)'
for (var f = 3; f*f <= num; f += 2) {
while (!(num % f)) { // remainder of 'num / f' isn't 0
factors.push(f);
num /= f;
}
}
/* if the number is already prime, then this adds it to factors so
* an empty array isn't returned
*/
if (num != 1) {
factors.push(num);
}
return factors;
}
This performs very well at large numbers compared to functions I've run it against, especially when the number is prime, (rarely runs slower than 10ms when I've run it in an online compiler like OneCompiler) so if you want speed I'd say this is a pretty good way to go about it.
Still working on making it even faster, but only way to include all primes without adding new conditions to check is to iterate through all odd numbers.
I just started JavaScript but i managed to come up with my own solution for this while working on a school project with a similar objective.
Only issue is that it takes a very long time for large numbers, its not v ery efficient. But it works perfectly.
function isPrime(n){
if (n === 1){
return false;
}
else if (n === 2){
return true;
}
else{
for (let x = 2; x < n; x ++){
if (n % x === 0){
return false;
}
}
return true;
}
}
let primeFac = []
let num = 30
for (let x = 0; x <= num; x++){
if (num % x === 0 && isPrime(x) === true){
primeFac.push(x);
}
}
console.log(`${primeFac}`)
If you work up from the bottom there's no need to check if any following factor is prime. This is because any lower primes will have already been divided out.
function getPrimeFactorsFor(num) {
const primes = [];
for (let factor = 2; factor <= num; factor++) {
while ((num % factor) === 0) {
primes.push(factor);
num /= factor;
}
}
return primes;
}
console.log("10 has the primes: ", getPrimeFactorsFor(10));
console.log("8 has the primes: ", getPrimeFactorsFor(8));
console.log("105 has the primes: ", getPrimeFactorsFor(105))
console.log("1000 has the primes: ", getPrimeFactorsFor(1000))
console.log("1155 has the primes: ", getPrimeFactorsFor(1155))
In case somebody is looking for the fastest solution, here's one based on my library prime-lib. It can calculate prime factors for any number between 2 and 2^53 - 1, in under 1ms. The function source code is available here.
import {primeFactors} from 'prime-lib';
const factors = primeFactors(600851475143);
//=> [71, 839, 1471, 6857]
Here an other implementation to find prime factors, in three variations. It's more efficient than the other implementations, worst case sqrt(n), because it stops earlier.
The function* means it's a generator function. So a generator is returned instead of an array and the next prime factor is only calculated as soon as it is requested.
// Example: 24 -> 2, 3
function* singlePrimeFactors (n) {
for (var k = 2; k*k <= n; k++) {
if (n % k == 0) {
yield k
do {n /= k} while (n % k == 0)
}
}
if (n > 1) yield n
}
// Example: 24 -> 2, 2, 2, 3
function* repeatedPrimeFactors (n) {
for (var k = 2; k*k <= n; k++) {
while (n % k == 0) {
yield k
n /= k
}
}
if (n > 1) yield n
}
// Example: 24 -> {p: 2, m: 3}, {p: 3, m: 1}
function* countedPrimeFactors (n) {
for (var k = 2; k*k <= n; k++) {
if (n % k == 0) {
var count = 1
for (n /= k; n % k == 0; n /= k) count++
yield {p: k, m: count}
}
}
if (n > 1) yield {p: n, m: 1}
}
// Test code
for (var i=1; i<=100; i++) {
var single = JSON.stringify(Array.from(singlePrimeFactors(i)))
var repeated = JSON.stringify(Array.from(repeatedPrimeFactors(i)))
var counted = JSON.stringify(Array.from(countedPrimeFactors(i)))
console.log(i, single, repeated, counted)
}
// Iterating over a generator
for (var p of singlePrimeFactors(24)) {
console.log(p)
}
// Iterating over a generator, an other way
var g = singlePrimeFactors(24)
for (var r = g.next(); !r.done; r = g.next()) {
console.log(r.value);
}
My solution avoids returning not prime factors:
let result = [];
let i = 2;
let j = 2;
let number = n;
for (; i <= number; i++) {
let isPrime = number % i === 0;
if (isPrime) {
result.push(i);
number /= i;
}
while (isPrime) {
if (number % i === 0) {
result.push(i);
number /= i;
} else {
isPrime = false;
}
}
}
return result;
With so many good solutions above, wanted to make a little bit of improvement by using this theorem in the Math Forum Finding prime factors by taking the square root
.
function primeFactors(n)
{
// Print the number of 2s that divide n
while (n%2 == 0)
{
console.log(2);
n = n/2;
}
// n must be odd at this point. So we can skip
// one element (Note i = i +2)
for (var i = 3; i <= Math.sqrt(n); i = i+2)
{
// While i divides n, print i and divide n
while (n%i == 0)
{
console.log(i);
n = n/i;
}
}
// This condition is to handle the case when n
// is a prime number greater than 2
if (n > 2)
console.log(n);
}
primeFactors(344);
console.log("--------------");
primeFactors(4);
console.log("--------------");
primeFactors(10);
Hope this answer adds value.
Here is a solution using recursion
function primeFactors(num, primes){
let i = 2;
while(i < num){
if(num % i === 0){
primes.push(i);
return primeFactors(num/i, primes);
}
i++
}
primes.push(num);
return primes;
}
console.log(primeFactors(55, []))
console.log(primeFactors(15, []))
console.log(primeFactors(40, []))
console.log(primeFactors(13, []))
// [ 5, 11 ]
// [ 3, 5 ]
// [ 2, 2, 2, 5 ]
// [ 13 ]
I found this solution by chance when i was trying to simplify several
solutions that i saw here. Although it doesn't check if the divisor
is a prime number somehow it seems to work, i tested it with
miscellaneous numbers but i could not explain how this was possible.
function start() {
var integer = readInt("Enter number: ");
println("The prime factorization is: ");
for(var i = 2; i <= integer; i++) {
if (integer % i == 0) {
println(i);
integer = integer / i;
i = i - 1;
}
}
}
I checked the algorithm with yield, but that is a lot slower than recursive calls.
function rootnth(val, power=2) {
let o = 0n; // old approx value
let x = val;
let limit = 100;
let k = BigInt(power);
while(x**k!==k && x!==o && --limit) {
o=x;
x = ((k-1n)*x + val/x**(k-1n))/k;
}
return x;
}
// Example: 24 -> 2, 2, 2, 3
function repeatedPrimeFactors (n,list) {
if (arguments.length == 1) list = "";
if (n % 2n == 0) return repeatedPrimeFactors(n/2n, list + "*2")
else if (n % 3n == 0) return repeatedPrimeFactors(n/3n, list + "*3")
var sqrt = rootnth(n);
let k = 5n;
while (k <= sqrt) {
if (n % k == 0) return repeatedPrimeFactors(n/k, list + "*" + k)
if (n % (k+2n) == 0) return repeatedPrimeFactors(n/(k+2n), list + "*" + (k+2n))
k += 6n;
}
list = list + "*" + n;
return list;
}
var q = 11111111111111111n; // seventeen ones
var t = (new Date()).getTime();
var count = repeatedPrimeFactors(BigInt(q)).substr(1);
console.log(count);
console.log(("elapsed=" + (((new Date()).getTime())-t)+"ms");
Here I try for the factors 2 and 3, followed by alternatingly adding 2 anf 4 (5,7,11,13,17,...) until the square root of the number.
Seventeen ones (which is not prime) takes about 1 second and nineteen ones (which is prime) eight seconds (Firefox).
Here is the solution with the nested function using the filter method.
function primeFactors(params) {
function prime(number) {
for (let i = 2; i < number + 1; ) {
if (number === 2) {
return true;
}
if (number % i === 0 && number !== i) {
return false;
} else if (i < number) {
i++;
} else {
return true;
}
}
}
let containerPrime = [];
let containerUnPrime = [];
for (let i = 0; i < params; i++) {
if (prime(i)) {
containerPrime.push(i);
} else {
containerUnPrime.push(i);
}
}
return containerPrime.filter((e) => params % e === 0);
}
console.log(primeFactors(13195));
function primeFactorization(n) {
let factors = [];
while (n % 2 === 0) {
factors.push(2);
n = n / 2;
}
for (let i = 3; i <= Math.sqrt(n); i += 2) {
while (n % i === 0) {
factors.push(i);
n = n / i;
}
}
if (n > 2) {
factors.push(n);
}
return factors;
}
console.log(primeFactorization(100));
The answer with O(sqrt(n)) complexity, it's faster than O(n):
const number = 13195;
let divisor = 2;
const result = [];
let n = number;
while (divisor * divisor <= number) {
if (n % divisor === 0) {
result.push(divisor);
n /= divisor;
} else {
divisor++;
}
}
if (n > 1) {
result.push(n);
}
console.log(result);
The above code (the code which has while loop) is correct, but there is one small correction in that code.
var num, i, factorsArray = [];
function primeFactor(num) {
for (i = 2; i <= num; i++) {
while (num % i == 0) {
factorsArray.push(i);
num = num / 2;
}
}
}
primeFactor(18);
var newArray = Array.from(new Set(factorsArray));
document.write(newArray);
This is my solution
function prime(n) {
for (var i = 1; i <= n; i++) {
if (n%i===0) {
myFact.push(i);
var limit = Math.sqrt(i);
for (var j = 2; j < i; j++) {
if (i%j===0) {
var index = myFact.indexOf(i);
if (index > -1) {
myFact.splice(index, 1);
}
}
}
}
}
}
var n = 100, arr =[],primeNo = [],priFac=[];
for(i=0;i<=n;i++){
arr.push(true);
}
//console.log(arr)
let uplt = Math.sqrt(n)
for(j=2;j<=uplt;j++){
if(arr[j]){
for(k=j*j;k<=n;k+=j){
arr[k] = false;
}
}
}
for(l=2;l<=n;l++){
if(arr[l])
primeNo.push(l)
}
for(m=0;m<primeNo.length;m++){
if(n%primeNo[m]==0)
priFac.push(primeNo[m])
}
console.log(...priFac);
var sum = 0
for (i = 0; i < 250; i++) {
function checkIfPrime() {
for (factor = 2; factor < i; factor++) {
if (i % factor = 0) {
sum = sum;
}
else {
sum += factor;
}
}
}
}
document.write(sum);
I am trying to check for the sum of all the prime numbers under 250. I am getting an error saying that i is invalid in the statement if (i % factor = 0) I know was creating in the original for statement, but is there any way to reference it in the if statement?
With the prime computation, have you considered using Sieve of Eratosthenes? This is a much more elegant way of determining primes, and, summing the result is simple.
var sieve = new Array();
var maxcount = 250;
var maxsieve = 10000;
// Build the Sieve, marking all numbers as possible prime.
for (var i = 2; i < maxsieve; i++)
sieve[i] = 1;
// Use the Sieve to find primes and count them as they are found.
var primes = [ ];
var sum = 0;
for (var prime = 2; prime < maxsieve && primes.length < maxcount; prime++)
{
if (!sieve[prime]) continue;
primes.push(prime); // found a prime, save it
sum += prime;
for (var i = prime * 2; i < maxsieve; i += prime)
sieve[i] = 0; // mark all multiples as non prime
}
document.getElementById("result").value =
"primes: " + primes.join(" ") + "\n"
+ "count: " + primes.length + "\n"
+ "sum: " + sum + "\n";
#result {
width:100%;
height:180px
}
<textarea id="result">
</textarea>
(EDIT) With the updated algorithm, there are now two max involved:
maxcount is the maximum number of prime numbers you wish to find
maxsieve is a guess of sieve large enough to contain maxcount primes
You will have to validate this by actually checking the real count since there are two terminating conditions (1) we hit the limit of our sieve and cannot find any more primes, or (2) we actually found what we're looking for.
If you were to increase the number to numbers much greater than 250, than the Sieve no longer becomes viable as it would be consume great deals of memory. Anyhow, I think this all makes sense right? You really need to play with the Sieve yourself at this point than rely on my interpretation of it.
You can equally use this
let sum = 0;
let num = 250;
for (let i = 2; i < num; i++) {
let isPrime = true;
for (let j = 2; j < i; j++) {
if (i % j === 0) {
isPrime = false;
}
}
if (isPrime) {
sum += i;
}
}
console.log(sum);
i % factor === 0
Use === for comparison. = is for assignment. Yeah I said triple equals. Type coercion is annoying.
You need a == or ===: if (i % factor == 0)
Here's a pretty decent way to do it. It's not as advanced as the sieve but it's a decent starting point. NOTE: I'm using ES6 syntax.
/*
* Sum the first n prime numbers
*
* #param n (integer)
* #return integer
*
*/
function sumNprimes(n){
const arr = [];
let i = 2
while (arr.length < n) {
if (isPrime(i)) {
arr.push(i)
}
i++
}
return arr.reduce( (x,y) => x+y );
/*
* #param n (integer)
* #return Boolean
*
*/
function isPrime(n) {
if ( n < 2 ) {
return false
}
for ( let i = 2; i <= Math.sqrt(n); i++ ) {
if ( n % i === 0 ) {
return false;
}
}
return true
}
}
So i had to face a similar challenge and here is my solution, i hope you find it helpful:
function sumPrimes(num) {
// determine if a number is prime
function isPrime(n) {
if (n === 2) return true;
if (n === 3) return true;
if (n % 2 === 0) return false;
if (n % 3 === 0) return false;
var i = 5;
var w = 2;
while (i * i <= n) {
if (n % i === 0) {
return false;
}
i += w;
w = 6 - w;
}
return true;
}
// subtract 1 for 'not being prime' in my context
var sum = isPrime(num) ? num - 1 : -1;
for (var x = 0; x < num; x++) {
if (isPrime(x) === true) {
sum += x;
}
}
return sum;
}
As per the "Sieve of Eratosthenes", I have implemented the code using JS:
function isPrime(n){
return ((n/2 === 1 || n/3 === 1 || n/5 === 1 || n/7 === 1)?true:(n%2===0 || n%3 === 0 || n%5 ===0 || n%7 === 0)?false:true);
};
var val = 250;
let outArr = [];
for(let i=2;i<val;i++){
if(isPrime(i)){
outArr.push(i);
}
}
console.log("Prime number between 0 - "+val+" : "+outArr.join(","));
Here is a simple way of looping through array and implementing the sieve of Eratosthenes...
function sumPrimes(num) {
var t, v = [],
w = [],
x = [],
y = [],
z = 0;
//enumerating Vee array starts at 2 as first prime number
for (let a = 2; a <= num; a++) {
v.push(a)
}
//creating a moving loop by splicing its first index
for (let i = 0; i < v.length; i) { //ensure all items spliced
t = v[i]; // t as prime to be removed from Vee array
x.push(t); // x storage of primes
z += t // total of peculiar primes
w.push(v.splice(i, 1)) //tested to move all one by one
// prompt(v) //tested that v loses its v[i] every iteration
//= now trying to remove others using remainder (%) vs prime t
for (let vi in v) {
v[vi] % t === 0 ? y.push(v.splice(vi, 1)) : ""; //recursive removal of composite items by prime t
}
}
return z // returns sum of primes
}
sumPrimes(250);
You generate the array beginning with 2 as first prime,
You sieve the array removing items by the remainder of prime using % === 0.
The you loop through the remaining array by using the next prime until the last remaining prime is pushed to the prime arrays. Add all primes to get the Sum.
If the question is purely academical, earlier answers are better suited.
The example below uses modern libraries, in case you need an efficient and elegant solution.
import {generatePrimes} from 'prime-lib';
import {from, reduce, takeWhile} from 'rxjs';
from(generatePrimes())
.pipe(takeWhile(p => p < 250), reduce((a, c) => a + c))
.subscribe(sum => {
// sum = 5830
});
Performance-wise, it will take significantly less than 1ms.
How would it affect the code if I wanted say the sum of the first 250 prime numbers instead of the prime numbers under 250?
You would just replace takeWhile(p => p < 250) with take(250):
import {generatePrimes} from 'prime-lib';
import {from, reduce, take} from 'rxjs';
from(generatePrimes())
.pipe(take(250), reduce((a, c) => a + c))
.subscribe(sum => {
// sum = 182109
});
P.S. I am the author of prime-lib.