Execution Timed Out problem on code wars.How to optimize the code - javascript

everyone.I was practicing on code wars and solving a problem aimed on prime numbers.I comleted it, but having submitted the program i get the message Execution Timed Out (12000 ms); Here is the program: `
function isPrime(number) {
let counter = 0;
for (let i=1;i<=number;i++){
if (number % i == 0) {
counter++;
}
}
if (counter == 2) {
return true
} else return false
}
function getPrimes(start, finish) {
let a = [];
let b = [];
if (start == 0 && finish == 0) {
return b;
}
if (start < finish) {
for (let i=start;i<=finish;i++){
a.push(i);
}
for (let j=0;j<a.length;j++) {
if (isPrime(a[j])) {
b.push(a[j]);
}
}
return b;
}
else if (start > finish) {
for (let i=finish;i<=start;i++){
a.push(i);
}
for (let j=0;j<a.length;j++) {
if (isPrime(a[j])) {
b.push(a[j]);
}
}
return b;
}
}
`
There are two funcs, the first one returns true if the number is prime and false if not.
and the second one takes start and finish like array borders and you need to return sorted array of prime numbers in these diapazon.I will be grateful for your help =)

Related

Javascript continue not working even when condition is met

The isPrime() function returns true if a number is a prime number and it returns false if not. The loop should go through 2 to 500 backward and run it in the isPrime() function. If the number is not a prime number the loop should continue to the next loop iteration. And also, for the number which is a prime number, it should output in the paragraph's textContent, but the continue is not working.
Here is the code:
let i = 500;
const para = document.createElement('p');
function isPrime(num) {
for(let i = 2; i < num; i++) {
if(num % i === 0) {
return false;
}
}
return true;
}
// Add your code here
while( i >= 2 ){
if( isPrime(i) === false){
continue;
} else{
para.textContent = `${i}` + "</br>";
}
i--;
}
And here is the fiddle: https://jsfiddle.net/au9o2ftn/1/
You can simply do this:
let i = 500;
function isPrime(num) {
for (let i = 2; i < num; i++) {
if (num % i === 0) {
return false;
}
}
return true;
}
while (i >= 2) {
if (isPrime(i)) {
console.log(i + " is prime!");
}
i--;
}
without continue...
The problem is that when isPrime(i) in your original code returns true, it continue directly and didn't finish i--. As a result, it becomes a dead loop with infinitely checking isPrime(500).
Or, if you wish to keep continue, put i-- before the continue statement.

Memoization giving less performance and taking more time

I was solving project euler in freecodecamp. When solving problem no 14 i use recursion and tried to increase the performance using memorization. But without memoization it is taking less time to execute and with memoization it is taking more time. Is memoization implementation is correct? What is wrong with this code? Can any one explain?
//Memoized version of the longestCollatzSequence project euler
let t1 = Date.now();
// function recurseWrapper(n) {
// let count = 0;
// let memo = {}
// function recurseCollatzSequence(n) {
// if (n in memo) {
// return memo[n];
// } else {
// if (n === 1) {
// return;
// } else if (n % 2 === 0) {
// count++;
// memo[n / 2] = recurseCollatzSequence((n / 2))
// } else {
// count++;
// memo[(3 * n) + 1] = recurseCollatzSequence(((3 * n) + 1))
// }
// return count
// }
// }
// return recurseCollatzSequence(n);
// }
//Without memoization (better performance)
function recurseWrapper(n) {
let count = 0;
function recurseCollatzSequence(n) {
if (n === 1) {
return;
} else if (n % 2 === 0) {
count++;
recurseCollatzSequence((n / 2))
} else {
count++;
recurseCollatzSequence(((3 * n) + 1))
}
return count
}
return recurseCollatzSequence(n);
}
function longestCollatzSequence(n) {
let max = 0;
let startNum = 0;
for (let i = n; i > 1; i--) {
let changeMax = recurseWrapper(i)
if (changeMax > max) {
max = changeMax;
startNum = i;
}
}
return startNum;
}
console.log(longestCollatzSequence(54512))
let t2 = Date.now() - t1;
console.log(`time taken by first instruction ${t2}`);
console.log(longestCollatzSequence(900000));
let t3 = Date.now() - t1 - t2
console.log(`time taken by second instruction ${t3}`);
let t4 = Date.now() - t1 - t2 - t3
console.log(longestCollatzSequence(1000000))
console.log(`time taken by third instruction ${t4}`);
From my limited understanding of the collatz conjecture, when starting at a number n, with all of the operations that you do, you should never see the same number again until you reach 1 (otherwise you would end up in an infinite loop). So your memo object will always hold unique keys that will never match the current number n, so if (n in memo) will never be true.
It actually seems that you want to memoize your results for further calls recurseWrapper() within your loop, so that you can prevent computing results you've already seen. At the moment you are not doing that, as you are creating a new memo object each time you call recurseWrapper(), removing all of the memoized values. You can instead return your inner auxiliary recursive wrapper function that closes over the memo object so that you keep the one memo object for all calls of the recursive wrapper function.
But even then we will still face issues, because of how the count is being calculated. For example, if you call recurseWrapper(n) and it takes 10 iterations to call recurseCollatzSequence(k), the returned count of recurseCollatzSequence(k) is going to be 10 plus whatever number it takes to compute the Collatz sequence for k. If we memoize this number, we can face issues. If we again call recurseWrapper on another number m, recurseWrapper(m), and this time it takes 20 iterations to get to the same call of recurseCollatzSequence(k), we will use our memoized value for k. But this value holds an additional count for the 10 that it took to get from n to k, and not just the count that it took to get from k to 1. As a result, we need to change how you're computing count in your recursive function so that it is pure, so that calling a function with the same arguments always produces the same result.
As Vincent also points out in a comment, you should be memoizing the current number, ie: memo[n] and not the number you're about to compute the Collatz count for (that memoization is done when you recurse):
function createCollatzCounter() {
const memo = {};
return function recurseCollatzSequence(n) {
if (n in memo) {
return memo[n];
} else {
if (n === 1) {
memo[n] = 0;
} else if (n % 2 === 0) {
memo[n] = 1 + recurseCollatzSequence(n / 2);
} else {
memo[n] = 1 + recurseCollatzSequence((3 * n) + 1);
}
return memo[n];
}
}
}
function longestCollatzSequence(n) {
let max = 0;
let startNum = 0;
const recurseWrapper = createCollatzCounter();
for (let i = n; i > 1; i--) {
let changeMax = recurseWrapper(i)
if (changeMax > max) {
max = changeMax;
startNum = i;
}
}
return startNum;
}
console.time("First");
console.log(longestCollatzSequence(54512));
console.timeEnd("First");
console.time("Second");
console.log(longestCollatzSequence(900000));
console.timeEnd("Second");
console.time("Third");
console.log(longestCollatzSequence(1000000));
console.timeEnd("Third");
In comparison, the below shows times without memo:
//Without memoization (better performance)
function recurseWrapper(n) {
let count = 0;
function recurseCollatzSequence(n) {
if (n === 1) {
return;
} else if (n % 2 === 0) {
count++;
recurseCollatzSequence((n / 2))
} else {
count++;
recurseCollatzSequence(((3 * n) + 1))
}
return count
}
return recurseCollatzSequence(n);
}
function longestCollatzSequence(n) {
let max = 0;
let startNum = 0;
for (let i = n; i > 1; i--) {
let changeMax = recurseWrapper(i)
if (changeMax > max) {
max = changeMax;
startNum = i;
}
}
return startNum;
}
console.time("First");
console.log(longestCollatzSequence(54512))
console.timeEnd("First");
console.time("Second");
console.log(longestCollatzSequence(900000));
console.timeEnd("Second");
console.time("Third");
console.log(longestCollatzSequence(1000000));
console.timeEnd("Third");
Here is a streamlined version of the solution with minimal noise around memoization and recursion.
let memo = {};
function collatzSequence(n) {
if (! (n in memo)) {
if (n == 1) {
memo[n] = 1;
}
else if ((n % 2) === 0) {
memo[n] = 1 + collatzSequence(n/2);
} else {
memo[n] = 1 + collatzSequence(3*n + 1);
}
}
return memo[n];
}
function longestCollatzSequence(n) {
let max = 0;
let startNum = 0;
for (let i = n; i > 1; i--) {
let changeMax = collatzSequence(i)
if (changeMax > max) {
max = changeMax;
startNum = i;
}
}
return startNum;
}
console.log(longestCollatzSequence(14))
And if you're willing to accept a bit of golf, here is a shorter version still of the first function.
let memo = {1: 1};
function collatzSequence(n) {
if (!(n in memo)) {
memo[n] = 1 + collatzSequence(0 === n%2 ? n/2 : 3*n+1);
}
return memo[n];
}
The reason why this matters has to do with how we think. As long as code reads naturally to us, how long it takes to write and think about it is directly correlated with how long it is. (This has been found to be true across a variety of languages in many places. I know that Software Estimation: Demystifying the Black Art certainly has it.) Therefore learning to think more efficiently about code will make it faster for you to write.
And that is why learning how to use techniques without talking about the technique you're using makes you better at that technique.
After spending some time figuring out I found a working solution.
The code below improved time complexity. Thanks all for helping me.
//Memoized version of the longestCollatzSequence project euler
let memo = {}
function recurseWrapper(n) {
let count = 0;
if (n in memo) {
return memo[n];
} else {
function recurseCollatzSequence(n) {
if (n === 1) {
return;
} else if (n % 2 === 0) {
count++;
recurseCollatzSequence((n / 2))
} else {
count++;
recurseCollatzSequence(((3 * n) + 1))
}
return count
}
let c = recurseCollatzSequence(n);
memo[n] = c;
return c;
}
}
function longestCollatzSequence(n) {
let max = 0;
let startNum = 0;
for (let i = n; i > 1; i--) {
let changeMax = recurseWrapper(i)
if (changeMax > max) {
max = changeMax;
startNum = i;
}
}
return startNum;
}
longestCollatzSequence(14)

Calculating complexity of js alghortim

I'm trying to caluclate complexity of below method in Big O notation
function algorithm(n,m){
let result = [];
for (let i = 0; i < n.length; i++) {
const total = m.filter((x) => x === n[i]).length;
if (PrimalityTest(total)) {
result.push(n[i]);
}
}
return result;
};
function PrimalityTest(c){
if (c <= 1) {
return false;
} else if (c === 2) {
return true;
} else {
for (let i = 2; i * i <= c; i++) {
if (c % i === 0) {
return false;
}
}
return true;
}
}
So, firstly there is loop which have O(n) and then there is nested loop and primality test function so that means complexity of all is O(n * m * sqrt(c))?
Can you please confirm If my understanding is correct?
The loop for (let i = 0; i < n.length; i++) is executed n times. The function m.filter((x) => x === n[i]).length checks every element in m, so executes m-times. So we have an execution time of O(n*m).
Considering
if (PrimalityTest(total)) {
result.push(n[i]);
}
is executed n times because it is in the same loop as above. So at worst it is O(n*sqrt(c))
To sum it up: It is O(n*m)+O(n*sqrt(c)). Because O(n*m) surpasses O(n*sqrt(c)) we get as result: O(n*m).
Your solution would mean that the filter function integrates the PrimalityTest method.

How to optimize the project euler #10 problem for FCC environment?

// the following code is generating accurate answer in my editor, but I want to optimize the code to pass the tests in freecodecamp environment. Can anybody shed the light upon this problem?
function isPrime(param) {
if (param == 2) {
return true;
}
if (param % 2 == 0) {
return false;
}
var max = Math.ceil(Math.sqrt(param));
for (var i = 3; i <= max; i += 2) {
if (param % i == 0) {
return false;
}
}
return true;
}
function primeSummation(n) {
var primeArr = [];
for (var i = 2; i < n; i++) {
if (isPrime(i)) {
primeArr.push(i);
}
}
var sumArray = primeArr.reduce(function add(a, b) {
return a + b;
}, 0);
console.log(sumArray)
return sumArray;
}
primeSummation(2000000);
When you have a long range of natural numbers (1...n) to check for them being prime, then it is not efficient to test them individually like you do with isPrime. It will be more efficient to perform the sieve of Eratosthenes over that range and then calculate the sum from the resulting array.

How to make recursive function on javascript without Maximum call stack size exceeded error?

I would like to make the same robot walk function with javascript but it get call stack size error.
http://www.chegg.com/homework-help/questions-and-answers/robot-take-steps-1-2-3-meters-write-program-allows-shows-possible-steps-robot-take-using-r-q3756383
function walk(meter) {
if(meter < 0) {
count = 0;
} else if(meter <= 2) {
count = meter;
} else if(meter == 3) {
count = walk(meter-1)+walk(meter-2)+1;
} else {
count = walk(meter-1)+walk(meter-2)+walk(meter-3);
}
return count;
}
console.log(walk(100));
It would exceed call stack size since your complexity is exponential, you can use memoization to solve your problem which helps covert an exponential time complexity into a polynomial one, now this code runs in O(100)
let obj = {};
function walk(meter) {
if(meter < 0) {
count = 0;
}
else if(obj[meter] != undefined){
return obj[meter];
} else if(meter <= 2) {
count = meter;
} else if(meter == 3) {
count = walk(meter-1)+walk(meter-2)+1;
} else {
count = walk(meter-1)+walk(meter-2)+walk(meter-3);
}
obj[meter] = count;
return count;
}
console.log(walk(100));

Categories