My Question
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 or equal to 10 are 1, 1, 3, and 5.
My Answer
function sumFibs(num, total = [1, 1]) {
const n = total[total.length - 1] + total[total.length - 2];
if(n > num){
return total;
}
if(n %2 ==0){
total.push(n);
}
return sumFibs(num, total);
}
sumFibs(4);
The Problem
It keeps saying maximum call stack exceeded. I am pretty sure it is because of the second if statement. Any idea how I can fix this?
I even tried this:
function sumFibs(num, total = [1, 1]) {
const n = total[total.length - 1] + total[total.length - 2];
if(n > num){
return total;
}
let x = Array.from(n);
let y = x.filter((item)=>{
return item % 2== 0
})
total.push(...y)
return sumFibs(num, total);
}
sumFibs(4);
I finally got there, so to explain:
I was not adding the even Fibonacci numbers to the array, as pointed out by Pointy. This was making the array incorrect.
This needed to move to the end. Once all of the Fibonacci calculations had been made. Then I could filter and reduce the break out clause of the recursive function:
function sumFibs(num, total = [1, 1]) {
const n = total[total.length - 1] + total[total.length - 2];
if(n > num){
let answer = total.filter((item)=>{
return item % 2 != 0;
}).reduce((totalII, filteredItems)=>{
return totalII + filteredItems
}, 0)
return answer
}
total.push(n)
return sumFibs(num, total);
}
console.log(sumFibs(4));
console.log(sumFibs(75204));
For contrast, here's an iterative, O(1) space, alternative:
function f(n){
if (n < 1)
return 0;
let result = 1;
let a = 1
let b = 1
while (b <= n){
if (b & 1)
result += b;
[a, b] = [b, a + b]
}
return result;
}
console.log(f(10));
console.log(f(4));
console.log(f(75204));
Related
I'm new to programming and learning about javascript recursion. It's my 5th day with JavaScript and following an online course.
The problem is that I need to sum up first n numbers of entries (first 3 numbers in this case) in an array.
But I'm ending up with sum of all and that also I'm not sure about.
var theArray = [1, 3, 8, 5, 7];
function sum(arr, n) {
if (n <= 0) {
return 1;
} else {
return arr[n - 1] + sum(arr, n - 2);
//assuming n is arr.length and n-1 is hence arr.length-1
}
}
console.log(sum(theArray, 3));
What am I doing wrong?
I checked most people are solving such with reduce method or with for of loop. I didn't learn those yet in the curriculum. But I know 'for loop' but that's good if the numbers are in incremental order I guess. Please explain this problem in my level.
When implementing something recursively, it's a good idea to think about the base condition. It does look like that's where you started, but your logic is flawed. n is the number of elements you would like to sum together. So let's say you want to sum the first n=3 elements of the array [2,3,4,5,6] and get 9. Here are the iterations.
return arr[n-1] + sum(arr, n-1) // arr[2] + sum(arr, 2) === 4 + sum(arr, 2) === 4 + 5
return arr[n-1] + sum(arr, n-1) // arr[1] + sum(arr, 1) === 3 + sum(arr, 2) === 3 + 2
return arr[n-1] // arr[0] === 2 (base case when n is 1)
I didn't solve the problem for you since this is obviously a school exercise, but the point is that the base case and the recursive call that you have are both slightly off.
Array of undetermined length, find the largest sum possible for any 3 consecutive numbers.
[2,0,1,100,200,10,7,2, 300,2,1 0] here 100,200,10 = 310 is the correct answer. Here only the combination of these 3 numbers produces the largest sum.
[2,1,0,20,71 = 0+20+7 = 27 is the answer that you should return.
const findMax = (numberArray) => {
let first = 0;
let second = 1;
let third = 2;
let max = 0;
for(; third < numberArray.length; first++, second++, third++) {
if(max < (numberArray[first] + numberArray[second] + numberArray[third])) {
max = numberArray[first] + numberArray[second] + numberArray[third];
}
}
return max;
}
console.log('Max sum of three consecutive numbers in array ===> ',findMax([2, 0, 100, 200, 10, 7, 2, 300, 2, 10]));
I'm totally stuck at one excersise question. Can someone help me out with this question?
Create a function sumRangeNumbers() that returns the sum of all numbers
between two chosen numbers. The function should take two arguments, one
representing the lowest boundary and one that represents the highest
boundary. For example, the arguments 10 and 20 should return the sum of
10+11+12+13...+20.
for (var i = 0; i < 82; i++) {
document.write(i + i + '+');
}
How do I write the loop that sums all the numbers with an function?
The answer of DCR already provides a nice implementation and is probably what you were looking for. However, with a little mathematical knowledge you can make the function a little easier.
We know that the sum of 1 to n is n(n+1)/2 by looking at this wikipedia page.
The sum of a to b, is simply the sum of 1 to b minus the sum of 1 to a - 1 (we also want to include a itself).
The sum between a and b is then b(b + 1)/2 - (a - 1)(a)/2 and therefore your function becomes:
const a = 10
const b = 20
function sumRangeNumbers(a, b) {
const high = Math.max(a, b);
const low = Math.min(a, b);
return high * (high + 1) / 2 - (low - 1) * (low) / 2;
}
console.log(sumRangeNumbers(a, b)); // 165
console.log(sumRangeNumbers(b, a)); // 165
console.log(sumRangeNumbers(5, 7)); // 18
function sumRangeNumber (num1, num2) {
let total = 0
for (let i = num1; i <= num2; i++) {
total += i
}
return total
}
You are on the right track with a for loop. What we did here was in place of declaring i as zero we passed the low value and in the comparison we pass the high value. This creates the range ie 10-20. From there each loop we add I too total which is declared outside fo the loop so as to not have it reset and we add to it.
As a previous comment mentioned, this is kinda doing your HW for you, so give the above function a shot and play around with it and change things to make sure you understand whats happening.
you need to first create a function and then you need to call it.
function sum(x,y){
var sum = 0;
for(let i = x;i<=y;i++){
sum = sum + i;
}
console.log(sum)
}
sum(1,10);
const sumRange = (num1, num2) => (
min = Math.min(num1, num2),
Array(Math.abs(num1 - num2) + 1)
.fill().map((_, i) => i + min)
.reduce((sum, el) => sum + el, 0)
);
console.log(sumRange(20, 10));
console.log(sumRange(10, 20));
function sumRangeNumbers(lower, upper) {
let total = 0;
for (let index=lower; index<=upper; index++) {
total = total + index;
}
return total;
}
document.write(sumRangeNumbers(10,20));
Simple:
function sumRangeNumbers(from, to) {
let result = 0;
for (let i = from; i <= to; i++) {
result += i;
}
return result;
}
If the numbers belong to range of natural numbers, then why do you need a loop. Just use the fact that sum from low to high=
((high-low+1) * (low + high)) / 2
Give this a shot:
function getSum(x,y) {
sum += x
console.log(sum, x)
if (x == y) { return sum }
else { return getSum(x+1,y) }
}
sum = 0
Here's a simple example using your current attempt. Keep in mind, you'll want to some error handling for cases where they give you an invalid high/low number.
IE:
if (lowNum >= highNum) { console.error('invalid range'); }
and maybe this too
if (typeof lowNum !== 'number' && typeof highNum !== 'number') { console.error('Invalid inputs'); }
function sumUp(lowNum, highNum) {
if (lowNum >= highNum) { throw new Error('Invalid Range'); }
// Initialize total at 0
let total = 0;
// Loop through numbers between lowNum and highNum.
// Do not include lowNum and highNum in the addition
for (let i = lowNum + 1; i < highNum; i++) {
// Increment the total with the 'in-between number (i)'
total += i;
}
// Return the result
return total;
}
// Test 1 (should be 44)
console.log(2 + 3 + 4 + 5 + 6 + 7 + 8 + 9, sumUp(1, 10));
// Test 2 (should be 315)
console.log(50 + 51 + 52 + 53 + 54 + 55, sumUp(49, 56));
// If you really want to do document.write
document.write(sumUp(49, 56));
// Test 3 (should fail)
console.log(sumUp(15, 3));
A number is gapful if it is at least 3 digits long and is divisible by the number formed by stringing the first and last numbers together.
The smallest number that fits this description is 100. First digit is
1, last digit is 0, forming 10, which is a factor of 100. Therefore,
100 is gapful.
Create a function that takes a number n and returns the closest gapful
number (including itself). If there are 2 gapful numbers that are
equidistant to n, return the lower one.
Examples gapful(25) ➞ 100
gapful(100) ➞ 100
gapful(103) ➞ 105
so to solve this i wrote the code that loops from the given number to greater than that and find out if it is or not by
function getFrequency(array){
var i=array
while(i>=array){
let a=i.toString().split('')
let b=a[0]+a[a.length-1]
b= +b
if(i%b==0) return i
i++
}
}
console.log(getFrequency(103))
Thats fine but what if the gapful number is less than the number passed in the function ?
like if i pass 4780 the answer is 4773 so in my logic how do i check simultaneoulsy smaller and greater than the number passed ?
I am only looping for the numbers greater than the number provided in function
You can alternate between subtracting and adding. Start at 0, then check -1, then check +1, then check -2, then check +2, etc:
const gapful = (input) => {
let diff = 0; // difference from input; starts at 0, 1, 1, 2, 2, ...
let mult = 1; // always 1 or -1
while (true) {
const thisNum = input + (diff * mult);
const thisStr = String(thisNum);
const possibleFactor = thisStr[0] + thisStr[thisStr.length - 1];
if (thisNum % possibleFactor === 0) {
return thisNum;
}
mult *= -1;
if (mult === 1) {
diff++;
}
}
};
console.log(
gapful(100),
gapful(101),
gapful(102),
gapful(103),
gapful(104),
gapful(105),
gapful(4780),
);
You could take separate functions, one for a check if a number is a gapful number and another to get left and right values and for selecting the closest number.
function isGapful(n) {
if (n < 100) return false;
var temp = Array.from(n.toString());
return n % (temp[0] + temp[temp.length - 1]) === 0;
}
function getClosestGapful(n) {
var left = n,
right = n;
while (!isGapful(right)) right++;
if (n < 100) return right;
while (!isGapful(left)) left--;
return n - left <= right - n
? left
: right;
}
console.log(getClosestGapful(25)); // 100
console.log(getClosestGapful(100)); // 100
console.log(getClosestGapful(103)); // 105
console.log(getClosestGapful(4780)); // 4773
I need a function that takes a and b both in [0..1] range, and adds a and b and returns the output in [0..1] range, when the sum is above 1 it wraps to zero like mod function.
I tried this but it doesn't work:
function shift(a, b) {
return (a + b) % 1;
}
For example for a = 1 and b = 0, it returns 0 but I want it to return 1.
I think the best you can do is something like:
function normalize(a, b) {
let r = (a + b);
return r === 1 ? 1 : r % 1;
}
This will return 0 when the sum is exactly 0, and 1 when the sum is exactly 1. Other values "wrap" back into the 0 ... 1 range.
I see three conditions here
1) When both of them are 1, the sum will be 2, in which case you have to return 0
2) When the sum is greater than 1, but not 2, in which case subtract 1
3) When the sum is less than 1, return the sum
function f(a,b){
s = (a+b)
if(s == 2)
return s-2
else if (s > 1)
return s-1
else
return s
}
I hope this helps.
OBJECTIVE
Given two numbers in an array, sum all the numbers including (and between) both integers (e.g [4,2] -> 2 + 3 + 4 = 9).
I've managed to solve the question but was wondering if there is a more elegant solution (especially using Math.max and Math.min) - see below for more questions...
MY SOLUTION
//arrange array for lowest to highest number
function order(min,max) {
return min - max;
}
function sumAll(arr) {
var list = arr.sort(order);
var a = list[0]; //smallest number
var b = list[1]; //largest number
var c = 0;
while (a <= b) {
c = c + a; //add c to itself
a += 1; // increment a by one each time
}
return c;
}
sumAll([10, 5]);
MY QUESTION(S)
Is there a more efficient way to do this?
How would I use Math.max() and Math.min() for an array?
Optimum algorithm
function sumAll(min, max) {
return ((max-min)+1) * (min + max) / 2;
}
var array = [4, 2];
var max = Math.max.apply(Math, array); // 4
var min = Math.min.apply(Math, array); // 2
function sumSeries (smallest, largest) {
// The formulate to sum a series of integers is
// n * (max + min) / 2, where n is the length of the series.
var n = (largest - smallest + 1);
var sum = n * (smallest + largest) / 2; // note integer division
return sum;
}
var sum = sumSeries(min, max);
console.log(sum);
The sum of the first n integers (1 to n, inclusive) is given by the formula n(n+1)/2. This is also the nth triangular number.
S1 = 1 + 2 + ... + (a-1) + a + (a+1) + ... + (b-1) + b
= b(b+1)/2
S2 = 1 + 2 + ... + (a-1)
= (a-1)a/2
S1 - S2 = a + (a+1) + ... + (b-1) + b
= (b(b+1)-a(a-1))/2
Now we have a general formula for calculating the sum. This will be much more efficient if we are summing a large range (e.g. 1 million to 2 million).
Here is a one liner recursive program solution of SumAll using es6.
const SumAll = (num, sum = 0) => num - 1 > 0 ? SumAll(num-1,sum += num) : sum+num;
console.log(SumAll(10));
Note :: Although the best Example is using the Algorithm, as mentioned above.
However if the above can be improved.