javascript: summing even members of Fibonacci series - javascript

Yet Another (Project Euler) Fibonacci Question: Using (vanilla) javascript, I'm trying to sum the even numbers <= a given limit:
First, something is wrong with my 'if' statement, as some of the results (below) are wrong:
function fibonacciSum(limit) {
var limit = limit;
var series = [1,2];
var sum = 0;
var counter = 0;
for (var i=1; i<=33; i++) { // 33 is arbitrary, because I know this is more than enough
var prev1 = series[series.length-1];
var prev2 = series[series.length-2];
var newVal = prev1+prev2;
series.push(newVal);
counter ++;
console.log("series "+ counter + " is: " + series);
if (series[i] % 2 === 0 && series[i] <= limit) { // intending to sum only even values less than/equal to arbitrary limit
// sum = sum + series[i];
sum += series[i];
}
/*
var sum = series.reduce(function(a,b) {
/*
possible to filter here for even numbers? something like:
if (a %2 === 0)
*/
return a+b;
});
*/
console.log("SUM " + counter + ": " + sum);
} // for loop
} // fibonacci
fibonacciSum(4000000);
Results:
series 1 is: 1,2,3
SUM 1: 2
series 2 is: 1,2,3,5
SUM 2: 2
series 3 is: 1,2,3,5,8
SUM 3: 2 // looking for a '10' here
series 4 is: 1,2,3,5,8,13
SUM 4: 10
series 5 is: 1,2,3,5,8,13,21
SUM 5: 10
series 6 is: 1,2,3,5,8,13,21,34
SUM 6: 10 // looking for '44' here
Can someone please explain why neither of these working as intended?
if (series[i] % 2 === 0) { ...
... or
if (series[i] % 2 === 0 && series[i] <= limit) { ...
And secondly, as you can see I had also tried to use series.reduce(... but I can't figure how to sum only the even values; is that doable/cleaner?
Thank you,
Whiskey T.

No need for arrays. Use three variables for let's say previous, current and next numbers in fibonacci sequence.
We can also begin the sequence with 2 an 3 because there are no other even numbers that will affect the result.
We initialize the sum of even numbers with 2 because it's the current number and it's even. In a do...while we advance with the numbers in sequence and if the new numbers are even we add them to the sum. Stop when limit is reached.
function fibEvenSum(limit) {
var prev = 1,
current = 2,
next;
var sum = 2;
do {
next = prev + current;
prev = current;
current = next;
if (current >= limit)
break;
if (current % 2 == 0)
sum += current;
} while (true)
return sum;
}
This algorithm can be improved using properties of odd and even numbers:
odd + odd = even
even + even = even
even + odd = odd

This should work for you...
var fibonacciSum = function(limit) {
var nMinus2 = 1, nMinus1 = 2, evensFound = [2], sum = nMinus1;
while (sum <= limit){
var n = nMinus1 + nMinus2;
if (n % 2 == 0){
sum += n;
if (sum > limit){
break;
}
evensFound.push(n);
}
nMinus2 = nMinus1;
nMinus1 = n;
}
console.log("Evens found - " + evensFound);
return evensFound;
};
var evensFound1 = fibonacciSum(4),
evensFound2 = fibonacciSum(10),
evensFound3 = fibonacciSum(60),
evensFound4 = fibonacciSum(1000);
$(evenResults).append(evensFound1
+ "<br/>" + evensFound2
+ "<br/>" + evensFound3
+ "<br/>" + evensFound4);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="evenResults"></div>

A solution in the spirit of the one your attempted — with arrays — though as pointed out, they are not necessary.
var i = 0, sequence = [1, 2], total = 0;
while (sequence.slice(-1)[0] < 4000000) {
sequence.push(sequence.slice(-1)[0] + sequence.slice(-2)[0]);
}
for ( i; i <= sequence.length; i++ ) {
if ( sequence[i] % 2 === 0 ) {
total += sequence[i];
}
}

Related

find all possible combinations of two integers

Each time I can climb 1 or 2 steps to reach the top (3 steps for example)
1 + 1 + 1, 1 + 2, 2 + 1. There are three cases (scenarios). Here's my voodoo code (the thing is some numbers (missing) don't appear for n = 5 it's 1211. the solution would be to do the reverse string and store two versions of such strings in the hash, so duplicates will disappear and after the cycle sums them.
function setCharAt(str, index, chr) {
if (index > str.length - 1) return str;
return str.substring(0, index) + chr + str.substring(index + 1);
}
let n = 9;
find(n);
function find(n) {
let origin = n; //every loop n decreases by one when it 0 while returns false,
let sum = 1;
n -= 1; //because n once once of 1's (n = 5) 1+1+1+1+1 then 1111, 1112 etc.
if (n <= 1) return sum;
while (origin <= n * 2) { //if n = 10; only"22222" can give 10, we don't go deeper
let str = "1".repeat(n); //from "1" of n(4) to "1111"
let copyStr = str;
while (str.length === copyStr.length) { //at the end we get 2222 then 22221,
// therefore the length will change, we exit the loop
let s = str.split('').reduce((a, b) => Number(a) + Number(b), 0); //countinng elems
console.log(str, "=", s);
if (s === origin) ++sum; //if elems equals the target we increase the amount by one
let one = str.lastIndexOf("1");
let two = str.lastIndexOf("2");
if (str[one] === "1" && str[one + 1] === "2") {
str = setCharAt(str, one, "2");
str = setCharAt(str, one + 1, "1");
} else {
str = setCharAt(str, one, "2");
}
}
--n;
}
console.log(sum)
}
If i understood your question, you wanna for let say n = 5 get all combinations of 1 and 2 (when you sum it) that give a sum of 5 (11111, 1112, etc)?
It is most likely that you wanna use recursion in these kind of situations, because its much easier. If you have just two values (1 and 2) you can achieve this pretty easily:
getAllCombinations = (n = 1) => {
const combinations = [];
const recursion = (n, sum = 0, str = "") => {
if (sum > n) return;
if (sum === n) {
combinations.push(str);
return;
}
// Add 1 to sum
recursion(n, sum + 1, str + "1");
// Add 2 to sum
recursion(n, sum + 2, str + "2");
};
recursion(n);
return combinations;
};

How can I count the number and calculate it? (i using isNaN())

My code is below. I'm using isNaN() but the problem is it's still valid
function numberSearch(str) {
let sum = 0
let strCount = 0
if (str === "") {
return 0
};
for (let i = 0; i < str.length; i++) {
if (isNaN(Number(str[i]))) {
strCount = strCount + 1 // if it's true, +1
}
sum = sum + Number(str[i]) // if it's a number
}
return Math.round(sum / strCount);
}
//debugger;
let output = numberSearch('Hello6 ');
console.log(output); // --> 1
output = numberSearch('Hello6 9World 2,');
console.log(output); // --> 1
How can I count the number and calculate it?
When I using debugger sum is NaN .. I cant understand well.
The issue is that sum = sum + Number(str[i]) is being executed even if isNaN(Number(str[i])) === true because it is outside of the if block. You need to wrap it inside of the else block so that it only executes if the previous condition is false.
function numberSearch(str) {
let sum = 0
let strCount = 0
if (str === "") {
return 0
};
for (let i = 0; i < str.length; i++) {
if (isNaN(Number(str[i]))) {
strCount = strCount + 1 // if it's true, +1
} else {
sum = sum + Number(str[i]) // if it's a number
}
}
return Math.round(sum / strCount);
}
//debugger;
let output = numberSearch('Hello6 ');
console.log(output); // --> 1
output = numberSearch('Hello6 9World 2,');
console.log(output); // --> 1
The other way of doing this is with a continue statement. Think of continue the same way you think about an early return in a function, except for a loop.
For example, you've written:
function numberSearch(str) {
// . . .
if (str === "")
return 0
// . . .
}
This is called an "early return" or "early exit." The same technique can be used in a loop:
for (let i = 0; i <= 10; i++) {
if (i % 3 === 0) // matches every multiple of 3 (3, 6, 9, etc.)
continue;
console.log(i)
}
Here is your code again, this time using continue.
function numberSearch(str) {
let sum = 0
let strCount = 0
if (str === "") {
return 0
};
for (let i = 0; i < str.length; i++) {
if (isNaN(Number(str[i]))) {
strCount = strCount + 1 // if it's true, +1
continue
}
sum = sum + Number(str[i]) // if it's a number
}
return Math.round(sum / strCount);
}
//debugger;
let output = numberSearch('Hello6 ');
console.log(output); // --> 1
output = numberSearch('Hello6 9World 2,');
console.log(output); // --> 1
I recommend you go with the if-else version because for a loop as simple as this, the use of continue adds a little unnecessary metal-overhead.
That being said, if the logic within the loop grows (the part in the else statement), you may find it is easy to read if you do use the continue method. In the end, what really matters is what you personally feel is easier to read.
I would probably do it slightly different than in the original code, and find out how many numbers there are, and work from there
function numberSearch(str) {
if (!str) {
// early exit for null or ''
return 0;
}
// get all the chars, filter the non-numbers
const numbers = str.split('').filter( v => !isNaN(Number(v)));
// map all the numbers to numbers and sum them up
const sum = numbers.map( Number ).reduce( (agg, item) => agg + item, 0 );
// divide the sum by the length of the string - the amount of numbers found
// but always by at least 1 (so not to get a divide by 0 error when only all numbers are given)
return Math.round( sum / Math.max(1, str.length - numbers.length) );
}
let output = numberSearch('Hello6 ');
console.log(output); // --> 1
output = numberSearch('Hello6 9World 2,');
console.log(output); // --> 2
output = numberSearch('111111111');
console.log(output); // --> 9
output = numberSearch('');
console.log(output);
For the original code however, you should just add a continue in your if branch and your code will work (as long as not all characters are numbers, cause then you would divide by 0 and you didn't specify how to handle such a case)
for (let i = 0; i < str.length; i++) {
if (isNaN(Number(str[i]))) {
strCount = strCount + 1; // if it's true, +1
continue;
}
sum = sum + Number(str[i]); // if it's a number
}
Just remember to verify to not divde by 0 if all are numbers :)
Your main issue is that you add a number anyway. In the line sum = sum + Number(str[i]) is read for each and every character. So even the last char will be NaN and it would be added to the sum, making it NaN.
I'm not quite sure what you're trying to do here, it seems like you are trying to get the sum and divide it by the number of non number characters.
You need to skip those in the sum. There are plenty of ways to do it, and some other problems with the code, but to keep the changes to your code to a minimum I say, just do this:
function numberSearch(str) {
let sum = 0;
let strCount = 0;
if (str === "") {
return 0;
};
for (let i = 0; i < str.length; i++) {
if (isNaN(Number(str[i]))) {
strCount = strCount + 1; // if it's true, +1
} else {
sum = sum + Number(str[i]); // if it's a number
}
}
return Math.round(sum / strCount);
}
Think of the following case
for(let i = 0 ; i<str.length ; i++){
//str[0] is 'H', so fall into the first if-case
if(isNaN(Number(str[i]))){
strCount = strCount + 1 // if it's true, +1
}
//the code keep running but 'H' shouldn't fall into the following case
sum = sum + Number(str[i]) // if it's a number
}
return Math.round(sum/strCount);
I suggest you add one more if-else for each case which clearly state out each of the case. This makes it easier to recall memory when you come across the code days or months later.
for(let i = 0 ; i<str.length ; i++){
if(isNaN(Number(str[i]))){
strCount = strCount + 1
}else if(typeof str[i] === 'number'){
sum = sum + Number(str[i])
}
}
return Math.round(sum/strCount);

find sum of multiples 3 and 5, JS

I'm given a number and I need to find the sum of the multiples of 3 and 5 below the number.
For example:
20 => 78 = 3 + 5 + 6 + 9 + 10 + 12 + 15 + 18
My code works, but not for numbers greater than 1,000,000 (I tested it for 100,000 - it gives the result with 2sec delay). So, it should be optimized. Could someone help me? Why is my code slow? Thanks.
My logic is as follows:
add multiples to an array
filter duplicate values
sum all values
my code:
function sumOfMultiples(number) {
let numberBelow = number - 1;
let numberOfThrees = Math.floor(numberBelow / 3);
let numberOfFives = Math.floor(numberBelow / 5);
let multiples = [];
let multipleOfThree = 0;
let multipleOfFive = 0;
for (var i = 0; i < numberOfThrees; i++) {
multiples.push(multipleOfThree += 3);
}
for (var j = 0; j < numberOfFives; j++) {
multiples.push(multipleOfFive += 5);
}
return multiples
.filter((item, index) => multiples.indexOf(item) === index)
.reduce((a, b) => a + b);
}
You can also do this without using any loops.
For example if N is 1000, the sum of all multiples of 3 under 1000 is 3 + 6 + 9 ..... 999 => 3( 1 + 2 + 3 .... 333)
Similarly for 5, sum is 5(1 + 2 + 3 .... 200). But we have to subtract common multiples like 15, 30, 45 (multiples of 15)
And sum of first N natural numbers is N*(N+1)/2;
Putting all of this together
// Returns sum of first N natural numbers
const sumN = N => N*(N+1)/2;
// Returns number of multiples of a below N
const noOfMulitples = (N, a) => Math.floor((N-1)/a);
function sumOfMulitples(N) {
const n3 = noOfMulitples(N, 3); // Number of multiples of 3 under N
const n5 = noOfMulitples(N, 5); // Number of multiples of 5 under N
const n15 = noOfMulitples(N, 15); // Number of multiples of 3 & 5 under N
return 3*sumN(n3) + 5*sumN(n5) - 15*sumN(n15);
}
You can just run a loop from 1 to number, and use the modulo operator % to check if i divides 3 or 5:
function sumOfMultiples(number) {
var result = 0;
for (var i = 0; i < number; i++) {
if (i % 5 == 0 || i % 3 == 0) {
result += i;
}
}
return result;
}
console.log(sumOfMultiples(1000));
console.log(sumOfMultiples(100000));
console.log(sumOfMultiples(10000000));
You can do that just using a single loop.
function sumOfMultiples(number) {
let sum = 0;
for(let i = 1; i < number; i++){
if(i % 3 === 0 || i % 5 === 0){
sum += i;
}
}
return sum;
}
console.time('t');
console.log(sumOfMultiples(100000))
console.timeEnd('t')
You can do something like this
Set the difference equal to 5 - 3
Start loop with current as 0, keep looping until current is less than number,
Add 3 to current in every iteration,
Add difference to current and check if it is divisible by 5 only and less than number, than add it final result,
Add current to final result
function sumOfMultiples(number) {
let num = 0;
let difference = 5 - 3
let current = 0
while(current < number){
current += 3
let temp = current + difference
if((temp % 5 === 0) && (temp %3 !== 0) && temp < number ){
num += temp
}
difference += 2
if(current < number){
num += current
}
}
return num
}
console.log(sumOfMultiples(20))
console.log(sumOfMultiples(1000));
console.log(sumOfMultiples(100000));
console.log(sumOfMultiples(10000000));
you can do something like this
function multiplesOfFiveAndThree(){
let sum = 0;
for(let i = 1; i < 1000; i++) {
if (i % 3 === 0 || i % 5 === 0) sum += i;
}
return sum;
}
console.log(multiplesOfFiveAndThree());

Calculate the sum of positive values smaller or equal to a number

I am trying to calculate the sum of positive values smaller or equal to the entered number, for ex: 5 -> 1+2+3+4+5 = 15
I came up with this:
var num = Number(prompt("Enter a number "));
sum = 0;
i = num;
do {
sum = sum += i;
i--
document.write(sum);
} while (i > 0);
I don't understand what I am doing wrong.
i think this is correct code:
var num = Number(prompt("Enter a number "));
sum = 0;
i = num;
do
{
sum += i;
i--;
}
while (i > 0);
document.write(sum);
and i suggest you to use this formula : document.write((num * (num + 1)) / 2);
If you look closer to your task, you'll find out, that:
If Num = 1, the sequence to be summed is [1]
if Num = 2, the sequence is [1, 2]
if Num = 3, the sequence is [1, 2, 3]
You can imagine, that you have a square with sides equal to num, for example, when num = 4:
****
****
****
****
And you need to summ 1, 2, 3, 4:
***#
**##
*###
####
See? It's a square of a triangle.
It could be calculated by formula: num * (num + 1) / 2
So, you code could be:
var num = Number(prompt("Enter a number "));
document.write(num * (num + 1) / 2)
You are writing the sum on each loop instead you have to print it finally. If you want to print the numbers then keep it an array and join them with + symbol before writing. To make it in ascending order change the loop condition.
var num = Number(prompt("Enter a number "));
sum = 0;
i = 1;
nums = [];
do {
sum = sum += i;
nums.push(i++);
}
while (i <= num);
document.write(nums.join(' + ') + ' = ' + sum);
Do with increment instead of decrements.And also show result of sum outside of loop .Not with in loop.And create array to append increment value.Finally print with document.write
var num=Number(prompt("Enter a number "));
sum = 0;
i = 1;
var a=[];
do {
sum +=i;
a.push(i)
i++;
}
while (num >= i);
document.write(a.join('+')+'='+sum)
You should write the answer at the end of loop and make this simple sum += i;.
var num = Number(prompt("Enter a number"));
sum = 0;
i = num;
do {
sum += i;
i--;
}
while (i > 0);
document.write(sum);
var number = 5, // Your number
result = 0;
while ( number !== 0 ) {
result += number;
number--;
}
document.write(result);
Fast and precious solution.
Here is the case with complete check and display as you need: JAVA
public static void main ( String arg[]) {
Scanner scan = new Scanner(System.in);
int number = scan.nextInt();
System.out.println("Number entered : " + number);
int sum =1 ;
if(number > 1) {
int nextNumber = 1;
System.out.print(nextNumber);
do {
// sum of all the positive numbers
nextNumber++ ;
sum = nextNumber + sum;
System.out.print( " + " + nextNumber);
}while(nextNumber < number);
System.out.print(" = " + sum);
}
}
var num = Number(prompt("Enter a number"));
sum = 0;
for (i = num; i > 0; i--) {
sum += i;
}
document.write(sum);

I need to sum all odd fibonacci numbers but only works for some numbers

Task: Given a positive integer num, return the sum of all odd Fibonacci numbers that are less than or equal to num.
The first two numbers in the Fibonacci sequence are 1 and 1. Every additional number in the sequence is the sum of the two previous numbers. The first six numbers of the Fibonacci sequence are 1, 1, 2, 3, 5 and 8.
For example, sumFibs(10) should return 10 because all odd Fibonacci numbers less than 10 are 1, 1, 3, and 5.
This is on freecodecamp. I have looked at examples I know I could of easily copied them but I wanted to write my own code, can someone explain why I get these results and where I've gone wrong? Thanks.
function sumFibs(num) {
var arr = [0, 1, 1]; //array of fibonacci numbers
var fin = 0; //variable for final number
for(var i = 3;i < 35;i++)
{
arr[i] = arr[i-1] + arr[i-2];
}
// loop to make fibonacci numbers
for(var x = 0; x < arr.length-1; x++)
{
if(arr[x] <= num && (arr[x] % 2 === 0))
{
fin += arr[x];
}//if to check if array of fibonacci numbers[x] is less than num && if it is odd
}//loop to go through every fibonacci number
return fin;
}
sumFibs(1000);
When you have the modulo operation:
if(arr[x] <= num && (arr[x] % 2 === 0))
You are asking two things:
if the arr[x] value is less than the number (check)
if the arr[x] value is even, NOT odd.
That is where your issue is occurring.
Rather you should use:
if(arr[x] <= num && (arr[x] % 2 != 0))
This is my solution :
function sumFibs(num)
{
var prev=0,curr=1,result=0,added;
while(curr<=num)
{
if(curr % 2 !=0)
{
result+=curr;
}
added= curr+prev;
prev=curr;
curr=added;
}
return result;
}
sumFibs(4);
Give this a try
function sumFibs(num) {
var firstNum = 0;
var secondNum = 1;
var sequence = [];
var index = [];
while (firstNum <= num) {
sequence.push(firstNum, secondNum);
firstNum = firstNum + secondNum;
secondNum = firstNum + secondNum;
/**/
}
for (var key in sequence) {
if (sequence[key] <= num) {
index.push(sequence[key]);
}}
//return index;
var oddIndex = [];
for (var key in index) {
if (index[key] % 2 !== 0) {
oddIndex.push(index[key]);
}
}
// return oddIndex;
var output = oddIndex.reduce(function(a,b){
return a+b;
});
return output;
}
sumFibs(75025); //should return 135721

Categories

Resources