function prime(number) {
var primeNumbers = [];
var numberDivide = 2;
for(var i=0; i<number; i++) {
var nice = number/numberDivide;
if(Math.floor(nice) == nice) {
number = nice;
primeNumbers.push(numberDivide);
} else {
numberDivide++
}
console.log(primeNumbers)
}
}
That is my code. It is not logging the final prime number, I don't know why. I went through and spoke it out loud but it isn't working...
First a code translation that works with integers to see what the function is doing:
function prime(number) {
var primeNumbers = [];
for(var divisor =2; divisor <= number;){
if( number % divisor == 0){
primeNumbers.push(divisor);
number = number/divisor;
continue;
}
++divisor;
}
return primeNumbers;
}
console.log( prime(18)); // returns [2,3,3]
Here number is replaced by the quotient of dividing it by a prime factor to see if additional prime factors can be found over and above those determined already. Note that number keeps getting smaller, and dividend is not incremented when found to be a factor so the next loop can test if it is a multiple factor.
So how many times does the loop iterate? This version doesn't count them, but the posted version stops iterating when the loop counter (not otherwise used) is greater or equal to number which as discussed keeps getting smaller.
The posted function fails for prime(18) and returns [2,3] instead of [2,3,3]. If it is allowed to iterate one more time it produces the correct result. I haven't looked into pre-calculating how many times to loop, but the method of finding when to exit the loop in the posted code is the cause of the problem.
Related
let arr=[0,1];
let sum=0;
for(let i=2;i<4000000;i++) {
arr.push(arr[i-1]+arr[i-2]);
}
for (let i=0;i<arr.length;i++) {
if (arr[i]%2==0) {
sum+=arr[i];
}
}
console.log(sum);
By considering the terms in the Fibonacci sequence whose values do not
exceed four million, find the sum of the even-valued terms.
My solution to this question is wrong and I can't figure out why at all. I am not that experienced so please if anyone can explain in a simple way why my code is wrong. What can I do to fix it??
Note: I haven't hadn't included code in this answer because I figure the point of what you're doing is to learn to code these things. (Now you've gotten most of the way there, I did add a solution at the end.)
The problem is that your sums quickly go beyond the range of what JavaScript's number type can represent, reaching the point where they just are represented by Infinity. The number type only has 53 effective significant bits in which to hold numbers. You're exceeding that:
let seen4M = false;
let seenInfinity = false;
let arr=[0,1];
let sum=0;
for(let i=2;i<4000000;i++) {
const num = arr[i-1]+arr[i-2];
if (!seen4M && num > 4_000_000) {
console.log(`Too big: ${num}`);
seen4M = true;
} else if (!seenInfinity && !isFinite(num)) {
console.log(`Overflowed just after ${arr[i-1]}`);
seenInfinity = true;
}
arr.push(num);
}
for (let i=0;i<arr.length;i++) {
if (arr[i]%2==0) {
sum+=arr[i];
}
}
console.log(sum);
You're doing four million (minus two) loops, but the question asks you to consider the Fibonacci numbers whose values are less than or equal to four million (4M), which is a very different thing and is reached much more quickly. So instead of (nearly) 4M loops, stop when your code determines that the next number is > 4M.
Also note that there's no reason to use an array for this, and doing so will consume a lot of memory unnecessarily. Instead, just remember the penultimate and ultimate values, and shuffle them in the loop. Maintain sum in the first loop rather than using a second one.
In a comment you showed that you'd solved it using an array but couldn't see how to solve it without using an array. Here's how to do that (see comments):
// The penultimate (second-to-last) Fibonacci number we've done
let pen = 0;
// The ultimate (last) Fibonacci number we've done
let ult = 1;
// The sum so far
let sum = 0;
// A variable for each number as we go
let num;
// Create the next number and keep looping if it's less than or
// equal to four million
while ((num = pen + ult) <= 4_000_000) {
// We have a new number (`num`), count it if appropriate
if (num % 2 == 0) {
sum += num;
}
// Now that we have a new number, shuffle the last two:
// our ultimate number is our penultimate number, and
// our ultimate number is the new one
pen = ult;
ult = num;
}
console.log(sum);
I have the following code:
function fib(n) {
let first=BigInt(0);
let snd=BigInt(1);
let currentNumber;
let countMax=Math.abs(n)+1;
let counter=2;
if(n==0){
return first;
}
else if (n==1||n==-1){
return snd;
}
while(counter<countMax)
{
currentNumber=first+snd;
first=snd;
snd=currentNumber;
counter++;
}
if((n<0) && (n % 2 ==0))
{
return -currentNumber;
}
return currentNumber;
}
That returns the fibonacci number for the given (n).
My issue is that I have to improve the performance of this code. I tried to use different fibonacci formulas (exponential ones) but I lose a lot of precision cause phi number has infinite decimals, so I have to truncate and for big numbers I lost a lot of precision.
When I execute for instance fib(200000) I get the huge number but the code spends more than 12000 ms.
For other hand I tried using recursion but the performance decreases.
Could you provide me an article or clue to follow?
Thanks & Regards.
First of all, you can refer the answer here which says that
Fib(-n) = -Fib(n)
Here's the recursive implementation which is not efficient as you mentioned
function fib(n) {
// This is to handle positive and negative numbers
var sign = n >= 0 ? 1 : -1;
n = Math.abs(n);
// Now the usual Fibonacci function
if(n < 2)
return sign*n;
return sign*(fib(n-1) + fib(n-2));
}
This is pretty straightforward and I leave it without explaining because if you know Fibonacci series, you know what the above code does. As you already know, this is not good for very large numbers as it recursively calculate the same thing again and again. But we'll use it in our approach later on.
Now coming towards a better approach. See the below code similar to your code just a bit concise.
function fib(n) {
if(n == 0)
return 0;
var a = 1;
var b = 1;
while(n > 2) {
b = a + b;
a = b - a;
}
// If n is negative then return negative of fib(n)
return n < 0 ? -1*b : b;
}
This code is better to use when you want to call this function only a few times. But if you want to call it for frequently, then you'll end up calculating the same thing many times. Here you should keep track of already calculated values.
For example, if you call fib(n) it will calculate nth Fibonacci number and return it. For the next time if you call fib(n) it will again calculate it and return the result.
What if we store this value somewhere and next time retrieve it whenever required?
This will also help in calculating Fibonacci numbers greater than nth Fibonacci number.
How?
Say we have to calculate fib(n+1), then by definition fib(n+1) = fib(n) + fib(n-1). Because, we already have fib(n) calculated and stored somewhere we can just use that stored value. Also, if we have fib(n) calculated and stored, we already have fib(n-1) calculated and stored. Read it again.
We can do this by using a JavaScript object and the same recursive function we used above (Yes, the recursive one!). See the below code.
// This object will store already calculated values
// This should be in the global scope or atleast the parent scope
var memo = {};
// We know fib(0) = 0, fib(1) = 1, so store it
memo[0] = 0;
memo[1] = 1;
function fib(n) {
var sign = n >= 0 ? 1 : -1;
n = Math.abs(n);
// If we already calculated the value, just use the same
if(memo[n] !== undefined)
return sign*memo[n];
// Else we will calculate it and store it and also return it
return sign*(memo[n] = fib(n-1) + fib(n-2));
}
// This will calculate fib(2), fib(3), fib(4) and fib(5).
// Why it does not calculate fib(0) and fib(1) ?
// Because it's already calculated, goto line 1 of this code snippet
console.log(fib(5)); // 5
// This will not calculate anything
// Because fib(-5) is -fib(5) and we already calculated fib(5)
console.log(fib(-5)); // -5
// This will also not calculate anything
// Because we already calculated fib(4) while calculating fib(5)
console.log(fib(4)); // 3
// This will calculate only fib(6) and fib(7)
console.log(fib(7)); // 13
Try out some test cases. It's easy to understand why this is faster.
Now you know you can store the already calculated values, you can modify your solution to use this approach without using recursion as for large numbers the recursive approach will throw Uncaught RangeError. I leave this to you because it's worth trying on your own!
This solution uses a concept in programming called Dynamic Programming. You can refer it here.
If you just add the previous value to the current one and then use the old current value as the previous one you get a significant improvement in performance.
function fib(n) {
var current = 1;
var previous = 0;
while (--n) {
var temp = current;
current += previous;
previous = temp;
}
return current;
}
console.log(fib(1)); // 1
console.log(fib(2)); // 1
console.log(fib(3)); // 2
console.log(fib(4)); // 3
console.log(fib(5)); // 5
You can also use an array in the parent scope to store the previous values to avoid redoing the same calculations.
var fibMap = [1, 1];
function fib(n) {
var current = fibMap[fibMap.length - 1];
var previous = fibMap[fibMap.length - 2];
while (fibMap.length < n) {
var temp = current;
current += previous;
previous = temp;
fibMap.push(current);
}
return fibMap[n - 1];
}
console.log(fib(1)); // 1
console.log(fib(2)); // 1
console.log(fib(3)); // 2
console.log(fib(4)); // 3
console.log(fib(5)); // 5
Benchmark for getting the 1000th number 3 times
https://www.hackerrank.com/contests/projecteuler/challenges/euler001
Here is the problem I'm confused what the parseInt readline statement
and also the the var n statement mainly..
when i run my code it seems to count up to ten twice probably a simple problem just not seeing it and was hoping I could get it explained so I can keep working on project euler problems
Thanks
function main() {
var t = parseInt(readLine());
var sum = 0;
var arr = [];
for(var a0 = 0; a0 < t; a0++){
var n = parseInt(readLine());
for (var i = 0; i < n; i++)
if (i % 3 === 0 || i % 5 === 0){
arr.push(i);
sum += i;
};
console.log(arr);
};
}
Maybe I'm not following exactly what is your question.
The parseInt is a javascript function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
The readLine() function is defined for you, it will give you "the next line" that was captured from standard in.
All (or most) of the hackerrank problems offer the input for the problem thru standard-in and expect the result from standard-out. So for this problem, hackerrank has created this boilerplate code for reading that input.
process.stdin.on('end', function () {
input_stdin_array = input_stdin.split("\n");
main();
});
There is filling the input_stdin_array array that is used on the readLine() function.
And about the
when i run my code it seems to count up to ten twice
The problem mentions:
First line contains T that denotes the number of test cases. This is followed by T lines, each containing an integer, N.
So you are printing the array T times (for the default test case is 2), so that why you probably see the "up to ten 2 times"
I hope this helped, and probably you could start with a couple of the https://www.hackerrank.com/domains/tutorials/30-days-of-code challenge so you get a better grasp of how to work on the problems.
Regards
Declare the array after the first for loop. You are using the same array for every test case, even though it still contains numbers from the previous test cases. Same for the sum.
for(var a0 = 0; a0 < t; a0++) {
var arr = [];
var sum = 0;
My solution to the below problem gives correct answer in the compiler but gets rejected by the online judge due to the following error: JS Allocation failed - process out of memory.
What should I change in my algorithm to get rid of this error?
Codewars Kata:You have to code a function getAllPrimeFactors wich take an integer as parameter and return an array containing its prime decomposition by ascending factors, if a factors appears multiple time in the decomposition it should appear as many time in the array.
exemple:
getAllPrimeFactors(100) returns [2,2,5,5] in this order.
This decomposition may not be the most practical.
You should also write getUniquePrimeFactorsWithCount, a function which will return an array containing two arrays: one with prime numbers appearing in the decomposition and the other containing their respective power.
exemple:
getUniquePrimeFactorsWithCount(100) returns [[2,5],[2,2]]
You should also write getUniquePrimeFactorsWithProducts an array containing the prime factors to their respective powers.
exemple:
getUniquePrimeFactorsWithProducts(100) returns [4,25]
Errors, if:
n is not a number
n not an integer
n is negative or 0
The three functions should respectively return
[], [[],[]] and [].
Edge cases:
if n=0, the function should respectively return [], [[],[]] and [].
if n=1, the function should respectively return [1], [[1],[1]], [1].
if n=2, the function should respectively return [2], [[2],[1]], [2].
The result for n=2 is normal. The result for n=1 is arbitrary and has been chosen to return a usefull result. The result for n=0 is also arbitrary but can not be chosen to be both usefull and intuitive.
([[0],[0]]
would be meaningfull but wont work for general use of decomposition,
[[0],[1]]
would work but is not intuitive.)
Here is my algorithm:
function getAllPrimeFactors(n) {
var fact=[];
while(n%2===0)
{
fact.push(2);
n=n/2;
}
var i=3;
while(i<=Math.floor(Math.sqrt(n)))
{
while(n%i===0)
{
fact.push(i);
n=n/i;
}
i++;
}
if(n>2)
{
fact.push(n);
}
return fact;
}
function getUniquePrimeFactorsWithCount(n) {
var fact=getAllPrimeFactors(n);
var i=0;
var count=[];
var unique=[];
var c=0;
while(i<fact.length)
{
if(fact[i]===fact[i+1])
{
c++;
}
else
{
count.push(c+1);
c=0;
unique.push(fact[i]);
}
i++;
}
var fact_count=[];
fact_count.push(unique);
fact_count.push(count);
return fact_count;
}
function getUniquePrimeFactorsWithProducts(n) {
var fact_count=getUniquePrimeFactorsWithCount(n);
var fact_prod=[];
var i=0;
while(i<fact_count[0].length)
{
var prod=1;
var j=1;
while(j<=fact_count[1][i])
{
prod*=fact_count[0][i];
j++;
}
fact_prod.push(prod);
i++;
}
return fact_prod;
}
Your problem is that you enter an endless loop if you are passed 0. You should make 0 and negatives into special cases.
Sum all the odd numbers of the Fibonacci Series up to and including the given number.
I can't figure out the syntax for the problem I'm having. The problem, The for loop, loop ends when it is greater than or equal to the value of the num, instead I want it to end with the, to be generated values of the start.
Is there any way to make it work?
function sumFibs(num) {
var odd = [1]; // Odd numbers of the Fibonacci series
var start = [0,1]; // Fibonacci series
// Generating the series and filtering out the odd numbers
for(i=1;i<num;i++) {
var sum = 0;
sum = start[i] + start[i-1];
start.push(sum);
if(sum%2 != 0) {
odd.push(sum);
}
}
// Generating sum of the odd numbers
var main = 0; // sum of the odd numbers
for(i=0;i<odd.length;i++) {
main += odd[i]
}
console.log(start);console.log(odd);return main
}
sumFibs(4);
It should be like that if I understand correctly
while(start.length<num)
{
your code will be here
}
Instead of working with two arrays, maybe it's less confusing to work with one and use Array.prototype.reduce to sum only the odd values.
function sumFibs(num) {
var fib = [0, 1];
var sum = 0;
var i = 2;
while (true) {
sum = fib[i-2] + fib[i-1];
if (sum > num) {
break;
}
fib.push(sum);
i++;
}
return fib.reduce(function(v0, v) {
return v0 + (v % 2 === 0 ? 0 : v);
}, 0);
}
Have a look at my attempt at this:
http://jsfiddle.net/copet80/xejz4ka2/
Isnt this a Project Euler question?
If I understand the problem right then your problem is in the for loop. More specific in its condition. The for loop in your case will repeat itself so many times how num is -1 because you start at i = 1 and i < num. So in you case it will repeat istself 12 times and reach a much higher number than 13 if I understand the problem right.
First of, Im a beginner but I was taught that you use a for loop if you know how many times something has to repeat. In this case you dont know how many times you have to repeat the for loop because you dont know when you reach the number 13.
In this case a while loop would be better I think and you set the condition for you number. So for example:
while(sum<=num){}
or like somone before me said:
while (true){
if(sum<num){
break;
}
This 2 codes will end if the SUM will exceed 13. I belive you dont want the Fibonaci number too exceed 13. In this scenario you have to make other conditions but im feeling its project euler i wont give tha answer here.
Again. you have the loop condition to end if the fib number exceeds 13. Your code looks for 13-1 fibonacci numbers.