How can I add a stopping instruction to my fibonacci sequence? - javascript

I am trying to use recursion to make the fibonacci algorithm. I would like to print all the fibonacci to this res variable and stop when I get past this num parameter. I would like to know how I can do this? This code:
function fibs(num) {
let i = 2;
let res = 0;
while (res < num) {
res = fibs(i - 1) + fibs(i - 2);
i++;
}
return res;
}
console.log(fibs(10));
I am getting a maximum call stack size exceeded error.

Notes:
⚠️ By using the first solution with small mistake like adding a big number, you can still exceed the maximum call stack size. If you think about the meaning of recursive function which is calling itself again and again, additionally it has a high calculation time.
👌 Using the second solution you are technically using only the current stack to calculate the result. Function looks larger but not that expensive.
Solutions:
First Solution - Recursive:
This solution just works much simpler than the original one if you still want to have a solution with recursion:
const fibs = (num) => {
if (num === 1 || num === 2) {
return 1;
}
return fibs(num - 1) + fibs(num - 2);
};
// 1, 1, 2, 3, 5, 8, 13, 21, 34, 55
for (let i = 1; i <= 10; i++) {
console.log(`fibs(${i}):`, fibs(i));
}
Second Solution - Non-Recursive:
There is always a better solution, if I would bet I would go rather for non recursive solution, please find an example below:
const fibs = (num) => {
if (num === 1 || num === 2) {
return 1;
}
let result = 1;
let resultPrevious = 1;
for(let i = 2; i < num; i++) {
const temp = result;
result += resultPrevious;
resultPrevious = temp;
}
return result;
};
// 1, 1, 2, 3, 5, 8, 13, 21, 34, 55
for (let i = 1; i <= 10; i++) {
console.log(`fibs(${i}):`, fibs(i));
}
I was interested how the non recursive solution is faster in case of running for fibs(30), please find the result below:
From the result, it seems the recursive solution was 98.86% slower at testing time for value 30.
I hope this helps!

Please try below code.
function fibs(num) {
let a = 0, b = 1;
console.log(a);
while (b < num) {
console.log(b);
const c = b;
b = a + b;
a = c;
}
}
fibs(100);

Other answers explained why your code has an issue.
Here is a simple way to write a recursive function that captures the Fibonacci numbers up to num:
const fibsTo = (num, a = 0, b = 1) =>
a > num
? []
: [a, ... fibsTo (num, b, a + b)]
console .log (fibsTo (10))
This stores the current state (the most recent two values, a and b) in parameters passed through the recursive calls, starting with default values. This returns [0, 1, 1, 2, 3, 5, 8]. If you prefer to start with [1, 1, 2, 3, ...], then change the function to start with a = 1, b = 1.
This is not tail-recursive, and could eventually run out of stack space. When tail-call optimization finally becomes ubiquitous in JS, there will be reasons to use tail-recursive versions, and it doesn't hurt to do so now. A tail-recursive version might look like this:
const fibsTo = (num, fibs = [], a = 0, b = 1) =>
a > num
? fibs
: fibsTo (num , [...fibs, a], b, a + b)
But there is another reason that such tail-recursion isn't so important for this problem: Long before you run out of stack space, you will run past the precision of Javascript integers. In fact, while Fibonacci # 79 is actually 14472334024676221, JS techniques like this will produce 14472334024676220, and the error will compound from there. This can be fixed by using BigInts, but it won't matter until there is wider support for proper tail calls.
This function has approximately the same running speed as the non-recursive version from norbitrial's answer, so as expected, recursion is not a performance-killer on a fundamentally recursive problem.

using recursion is not the appropriate way when expecting a lot of calls.
this will make your code working slower, and in some cases - reach the maximum call stack size and get no answer.
the right way to do it is using array, like this:
function fibs(num) {
let i = 1;
let arr = [1, 1];
while (arr[i] < num) {
arr.push(arr[i-1] + arr[i]);
i++;
}
return arr[i];
}

Here's a snippet of what should you write to accomplish your task
function fibs(num) {
let res = 0;
let a = 0, b = 1;
while(res < num){
res = a + b;
a = b;
b = res;
}
return res;
}
console.log(fibs(10));

Because its not a recursion, its an infinite loop you are dealing with.
your code increment i (i++) but it dosent check in the while loop.
you can try this out:
function fibs(num) {
if (num>1) {
return (fibs(num - 1) + fibs(num - 2));
}
return num;
}

Related

Recursively going through permutations without storing in memory

I'm trying to go through all possible permutations of an array using a recursive function.
The permutations don't need to be stored in memory. They are being processed right away by the recursive function.
The idea is that the recursive function has an argument 'used' which keeps track of the elements that are 'fixed' at this point in the recursion tree, and an argument 'free' which keeps track of the elements that are not fixed yet at this point (i.e. they will be rearranged in the recursion steps going down the tree from there). So the first time, the function is called with an empty 'used' array and a full 'free' array.
Somehow my code below doesn't work yet. It only processes the first permutation successfully.
const elements = [7, 23, 41, 65, 99]
const n = elements.length;
handlePermutations([], elements);
function handlePermutations(used, free) {
if (used.length<n) {
for (i = 0; i < free.length; i++) {
newUsed = used.concat(free[i]); // add element i from free to used
newFree = free.filter(x => x != free[i]) // remove element i from free
handlePermutations(newUsed, newFree);
}
} else {
// ... 'process' this permutation (do something useful with it) ...
}
}
You're using (implicitly declared) global i, so it doesn't reset for each functions.
change it to let i fix the problem
const elements = [7, 23, 41, 65, 99]
const n = elements.length;
handlePermutations([], elements);
function handlePermutations(used, free) {
if (used.length < n) {
for (let i = 0; i < free.length; i++) {
let newUsed = used.concat(free[i]); // add element i from free to used
let newFree = free.filter(x => x != free[i]) // remove element i from free
handlePermutations(newUsed, newFree);
}
} else {
console.log(...used)
// ... 'process' this permutation (do something useful with it) ...
}
}
btw, your current free.filter(...) breaks if you have duplicate items. One possible way is simply change it to check passed in index.
free.filter((x,index) => index!=i)
Out of interest, here is a generator version of the same algorithm (with some changes).
const elements = [1, 2, 3, 4, 5]
for (let item of Permutations(elements)) {
console.log(...item)
}
// note: this (OP's) algorithm use O(n**2) space afaict
function Permutations(elements) {
return handlePermutations([], elements)
function* handlePermutations(used, free) {
if (free.length == 0)
yield used;
else {
for (let i = 0; i < free.length; i++) {
let newUsed = used.concat(free[i]) // add element i from free to used
let newFree = free.filter((x, index) => index != i) // remove element i from free
yield* handlePermutations(newUsed, newFree);
}
}
}
}
Another approach has you pass the callback function that will be used with each permutation.
const excludeIndex = (i) => (xs) =>
[... xs .slice (0, i), ... xs .slice (i + 1)]
const handlePermutations = (fn) => (free, used = []) =>
free.length == 0
? fn (used)
: free .forEach (
(e, i) => handlePermutations (fn) (excludeIndex (i) (free), [...used, e])
)
handlePermutations (xs => console. log(...xs)) ([7, 23, 41, 65])
.as-console-wrapper {max-height: 100% !important; top: 0}
We include the simple helper excludeIndex, which returns a copy of the array with the index missing. We use that in the recursive call along with the concatenation of the current element to used.
I'm not much of a fan of code written only for side-effects, but as that is the fundamental goal in the question, I can certainly live with it here.
Time complexity is unavoidably O (n!). Space complexity I think is O (n), since free and used together hold the original n elements. (Oops, see the comments!) Space complexity is O (n^2)
A different approach to this. Using a single integer to determine a distinct permutation of that array.
So generating all permutations for an array and processing them would be:
function permutation(array, n) {
let result = array.slice(); // don't mutate the input
for (let i = 0, rest = result.length; rest > 1 && n > 0; ++i, n = Math.floor(n / rest--)) {
let j = n % rest + i;
if (i === j) continue;
const tmp = result[i];
result[i] = result[j];
result[j] = tmp;
}
return result;
}
const elements = [1, 2, 3, 4, 5];
const length = elements.reduce((a,_,i) => a*(i+1), 1);
//const length = 5 * 4 * 3 * 2 * 1;
const map = {};
for (let i = 0; i <= length; ++i) {
map[i] = permutation(elements, i).join();
}
console.log(map);
console.log("map[120] === map[0]", "We're back at the start. From now on this will just loop the results.");
console.log("expected %i, got %i (different values/permutations in the results)", length, new Set(Object.values(map)).size);
.as-console-wrapper{top:0;max-height:100%!important}
You said without storing. I'm using the map above because this snippet would only store the last 50 console.logs while it shows all 120 entries/lines in the map. And to show at the end that it creates no duplicates, that there are indeed 120 different permutations in that map.
You could take a simplified approach and hand over just an array of indices and take two rules:
If the last element is greater then the previous element, swap both.
Search for an index from the end of the array where the element is greater than left and right element.
If found, search for the next grater element on the right side of the found index inclusive of the actual index, take this as new element in front of the group, sort the rest and apply.
If not found, end recursion.
function next([...array]) {
console.log(...array);
if (array[array.length - 2] < array[array.length - 1]) {
[array[array.length - 2], array[array.length - 1]] = [array[array.length - 1], array[array.length - 2]];
return next(array);
}
let index = array.length - 1;
while (--index) {
if (array[index - 1] < array[index] && array[index] > array[index + 1]) {
let value = Math.min(...array.slice(index - 1).filter(v => v > array[index - 1]))
array = [
...array.slice(0, index - 1),
value,
...array.slice(index - 1).filter(v => v !== value).sort((a, b) => a - b)
];
break;
}
}
if (!index) return;
return next(array);
}
next([0, 1, 2, 3, 4]);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Write a function that will return the two number array combination with value summed at 5. I can't get all the opportunities

A job posting wants me to write a an answer to a question which if I solve I am eligible for the next rownd.
Write a function that will return the array combination with value
summed at 5. Important: Use only one "for" loop. Example: var
rand_array = [1,3,5,2,4,6]; var target_sum = 5; Output = [1,4], [5],
[3,2], [2,3], [4,1];
I attempted to find a solution online and stumbled upon this:
https://www.geeksforgeeks.org/given-an-array-a-and-a-number-x-check-for-pair-in-a-with-sum-as-x/ as StackOverflow wants you to do your own research first.
However, when trying to convert it to JS, all that happened was that it returned just one case where it worked. I need it to return every case where it worked. I then make some other changes and it just stopped working now.
var ra = [1,3,5,2,4,6];
var target = 5
ra.sort();
lower = 0;
higher = ra.length -1;
var solutions = [];
var result;
while (lower < higher) {
if (ra[lower] + ra[higher] === target){
result = [ra[lower], ra[higher]];
solutions.push(result);
}
else if (ra[lower] + ra[higher] > target){
higher--;
}
else {
lower++;
}
}
return solutions;
}
console.log(solutions);
Can someone write an example for me?
Your code does not work at all at the moment because it doesn't always increment lower or higher (resulting in an infinite loop). It also has greater complexity than necessary (.sort has complexity O(n log n)), but the instructions indicate that low complexity is important. The array also isn't being sorted numerically. (To sort numerically, use .sort((a, b) => a - b))
If you want a solution with the least complexity possible, O(n), while iterating, create an object. On every iteration, check to see if the object has a key for which the current number would sum with to 5 (eg, when iterating on 1, look to see if a 4 property exists on the object). If one is found, add it to the solutions. Otherwise, set a new key on the object:
const ra = [1, 3, 5, 2, 4, 6];
const target = 5;
const solutions = [];
const obj = {};
for (const item of ra) {
const match = target - item;
if (obj[match]) {
solutions.push([item, match]);
delete obj[match];
} else {
obj[item] = true;
}
}
console.log(solutions);
If there may be repeated numbers, then store a count in the object instead of just true:
const ra = [1, 1, 1, 3, 5, 2, 4, 6, 4, 4];
const target = 5;
const solutions = [];
const obj = {};
for (const item of ra) {
const match = target - item;
if (obj[match]) {
solutions.push([item, match]);
obj[match]--;
} else {
obj[item] = (obj[item] || 0) + 1;
}
}
console.log(solutions);
I don't want to write the actual answer because its a job assignment, but I will say that a simple 2 loop function is the obvies solution, than try to think not checking the array from the top and the bottum, rether like the formation of a loop in a loop.
hint :
let i = 0;
let j = 0;
while (i < arr.langth) {
...
if (j < arr.langth) {
j++;
} else {
j = 0;
i++;
}
}
Your code as it stands just does not work at all. CertainPerformance has a solid answer, except that it doesn't do the task as required, i.e. treat the same numbers in a different order as different or get the values which are equal to target as solutions. Here is my solution to your problem:
const ra = [1,3,5,2,4,6];
const target = 5
function getSumsOfTarget(ra, target){
ra.sort();
lower = 0;
higher = ra.length -1;
const solutions = [];
let result;
while (lower < ra.length && higher >= 0) {
const sum = ra[lower] + ra[higher];
if (ra[lower] === target) {
result = [ra[lower]];
solutions.push(result);
break;
}
if (sum === target){
result = [ra[lower], ra[higher]];
solutions.push(result);
lower++;
}
else if (sum > target){
higher--;
}
else {
lower++;
}
}
return solutions;
}
console.log(getSumsOfTarget(ra, target));

Checking whether the number of unique numbers within array exceeds n

Just as title reads, I need to check whether the number of unique entries within array exceeds n.
Array.prototype.some() seems to fit perfectly here, as it will stop cycling through the array right at the moment, positive answer is found, so, please, do not suggest the methods that filter out non-unique records and measure the length of resulting dataset as performance matters here.
So far, I use the following code, to check if there's more than n=2 unique numbers:
const res = [1,1,2,1,1,3,1,1,4,1].some((e,_,s,n=2) => s.indexOf(e) != s.lastIndexOf(e) ? false : n-- ? false : true);
console.log(res);
.as-console-wrapper { min-height: 100%}
And it returns false while there's, obviously 3 unique numbers (2,3,4).
Your help to figure out what's my (stupid) mistake here is much appreciated.
p.s. I'm looking for a pure JS solution
You can use a Map() with array values as map keys and count as values. Then iterate over map values to find the count of unique numbers. If count exceeds the limit return true, if not return false.
Time complexity is O(n). It can't get better than O(n) because every number in the array must be visited to find the count of unique numbers.
var data = [1, 1, 2, 1, 1, 3, 1, 1, 4, 1];
function exceedsUniqueLimit(limit) {
var map = new Map();
for (let value of data) {
const count = map.get(value);
if (count) {
map.set(value, count + 1);
} else {
map.set(value, 1);
}
}
var uniqueNumbers = 0;
for (let count of map.values()) {
if (count === 1) {
uniqueNumbers++;
}
if (uniqueNumbers > limit) {
return true;
}
}
return false;
}
console.log(exceedsUniqueLimit(2));
To know if a value is unique or duplicate, the whole array needs to be scanned at least once (Well, on a very large array there could be a test to see how many elements there is left to scan, but the overhead for this kind of test will make it slower)
This version uses two Set
function uniqueLimit(data,limit) {
let
dup = new Set(),
unique = new Set(),
value = null;
for (let i = 0, len = data.length; i < len; ++i) {
value = data[i];
if ( dup.has(value) ) continue;
if ( unique.has(value) ) {
dup.add(value);
unique.delete(value);
continue;
}
unique.add(value);
}
return unique.size > limit;
}
I also tried this version, using arrays:
function uniqueLimit(data, limit) {
let unique=[], dup = [];
for (let idx = 0, len = data.length; idx < len; ++idx) {
const value = data[idx];
if ( dup.indexOf(value) >= 0 ) continue;
const pos = unique.indexOf(value); // get position of value
if ( pos >= 0 ) {
unique.splice(pos,1); // remove value
dup.push(value);
continue;
}
unique.push(value);
}
return unique.length > limit;
};
I tested several of the solutions in this thread, and you can find the result here. If there are only a few unique values, the method by using arrays is the fastest, but if there are many unique values it quickly becomes the slowest, and on large arrays slowest by several magnitudes.
More profiling
I did some more tests with node v12.10.0. The results are normalized after the fastest method for each test.
Worst case scenario: 1000000 entries, all unique:
Set 1.00 // See this answer
Map 1.26 // See answer by Nikhil
Reduce 1.44 // See answer by Bali Balo
Array Infinity // See this answer
Best case scenario: 1000000 entries, all the same:
Array 1.00
Set 1.16
Map 2.60
Reduce 3.43
Question test case: [1, 1, 2, 1, 1, 3, 1, 1, 4, 1]
Array 1.00
Map 1.29
Set 1.47
Reduce 4.25
Another test case: [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,
1,1,1,1,1,1,1,3,4,1,1,1,1,1,1,1,2,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,5 ]
Array 1.00
Set 1.13
Map 2.24
Reduce 2.39
Conclusion
The method that uses Set works for both small and large arrays, and performs well regardless of if there are many unique values or not. The version that are using arrays can be faster if there are few unique values, but quickly becomes very slow if there are many unique values.
Using sets, We count hypothetical unique set size and duplicateSet size and delete unique set element for each duplicate found. If unique set size goes below n, we stop iterating.
function uniqueGtN(res, n) {
let uniqSet = new Set(res);
let max = uniqSet.size;
if (max <= n) return false;
let dupSet = new Set();
return !res.some(e => {
if (dupSet.has(e)) {
if (uniqSet.has(e)) {
uniqSet.delete(e);
console.log(...uniqSet);
return (--max <= n);
}
} else {
dupSet.add(e);
}
});
}
console.log(uniqueGtN([1, 1, 2, 1, 1, 3, 3, 1], 2));
From your original solution, I have changed few things, it seems to be working fine:
(function() {
const array = [1,1,2,1,1,3,1,1,4,1];
function hasExceedingUniqueNumber(array, number) {
return array.some((e,_,s,n=number) => {
let firstIndex = s.indexOf(e);
let lastIndex = s.lastIndexOf(e);
// NOT unique
if (firstIndex != lastIndex) {
return false;
}
// unique
return e > n;
});
}
console.log('1', hasExceedingUniqueNumber(array, 1));
console.log('2', hasExceedingUniqueNumber(array, 2));
console.log('3', hasExceedingUniqueNumber(array, 3));
console.log('4', hasExceedingUniqueNumber(array, 4));
})();
So the shorter version looks like this:
(function() {
const array = [1,1,2,1,1,3,1,1,4,1];
function hasExceedingUniqueNumber(array, number) {
return array.some((e,_,s,n=number) => s.indexOf(e) != s.lastIndexOf(e) ? false : e > n);
}
console.log('1', hasExceedingUniqueNumber(array, 1));
console.log('2', hasExceedingUniqueNumber(array, 2));
console.log('3', hasExceedingUniqueNumber(array, 3));
console.log('4', hasExceedingUniqueNumber(array, 4));
})();
The code listed in your question does not work because m is not shared across the calls to the some callback function. It is a parameter, and its value is 2 at each iteration.
To fix this, either put m outside, or use the thisArg of the some function (but that means you can't use an arrow function)
let m = 2;
const res = [1,1,1,2,1,1,3,1,1,1,4,1,1]
.sort((a,b) => a-b)
.some((n,i,s) => i > 0 && n == s[i-1] ? !(m--) : false);
// ----- or -----
const res = [1,1,1,2,1,1,3,1,1,1,4,1,1]
.sort((a,b) => a-b)
.some(function(n,i,s) { return i > 0 && n == s[i-1] ? !(this.m--) : false; }, { m: 2 });
Note: this code seems to count if the number of duplicates exceeds a certain value, not the number of unique values.
As another side note, I know you mentioned you did not want to use a duplicate removal algorithm, but performant ones (for example hash-based) would result in something close to O(n).
Here is a solution to count all the values appearing exactly once in the initial array. It is a bit obfuscated and hard to read, but you seem to be wanting something concise. It is the most performant I can think of, using 2 objects to store values seen at least once and the ones seen multiple times:
let res = [1,1,2,3,4].reduce((l, e) => (l[+!l[1][e]][e] = true, l), [{},{}]).map(o => Object.keys(o).length).reduce((more,once) => once-more) > 2;
Here is the less minified version for people who don't like the short version:
let array = [1,1,2,3,4];
let counts = array.reduce((counts, element) => {
if (!counts.atLeastOne[element]) {
counts.atLeastOne[element] = true;
} else {
counts.moreThanOne[element] = true;
}
return counts;
}, { atLeastOne: {}, moreThanOne: {} });
let exactlyOnceCount = Object.keys(counts.atLeastOne).length - Object.keys(counts.moreThanOne).length;
let isOverLimit = exactlyOnceCount > 2;
Whenever I have a type of problem like this, I always like to peek at how the underscore JS folks have done it.
[Ed again: removed _.countBy as it isn't relevant to the answer]
Use the _.uniq function to return a list of unique values in the array:
var u = _.uniq([1,1,2,2,2,3,4,5,5]); // [1,2,3,4,5]
if (u.length > n) { ...};
[ed:] Here's how we might use that implementation to write our own, opposite function that returns only non-unique collection items
function nonUnique(array) {
var result = [];
var seen = [];
for (var i = 0, length = array.length; i < length; i++) {
var value = array[i];
if (seen.indexOf(value) === -1) { // warning! naive assumption
seen.push(value);
} else {
result.push(value);
}
}
console.log("non-unique result", result);
return result;
};
function hasMoreThanNUnique(array, threshold) {
var uArr = nonUnique(array);
var accum = 0;
for (var i = 0; i < array.length; i++) {
var val = array[i];
if (uArr.indexOf(val) === -1) {
accum++;
}
if (accum > threshold) return true;
}
return false;
}
var testArrA = [1, 1, 2, 2, 2, 3, 4, 5]; // unique values: [3, 4, 5]
var testArrB = [1, 1, 1, 1, 4]; // [4]
var testResultsA = hasMoreThanNUnique(testArrA, 3)
console.log("testArrA and results", testResultsA);
var testResultsB = hasMoreThanNUnique(testArrB, 3);
console.log("testArrB and results", testResultsB);
So far, I came up with the following:
const countNum = [1,1,1,2,1,1,3,1,1,1,4,1,1].reduce((r,n) => (r[n]=(r[n]||0)+1, r), {});
const res = Object.entries(countNum).some(([n,q]) => q == 1 ? !(m--) : false, m=2);
console.log(res);
.as-console-wrapper{min-height:100%}
But I don't really like array->object->array conversion about that. Is there a faster and (at the same time compact) solution?

Javascript for loop write to array undefined

Hi im doing the first part of eloquent javascript chp4 The Sum of a Range.
After spending some time i was sure i cracked the first part.
"Write a range function that takes two arguments, start and end,
and returns an array containing all the numbers from start
up to (and including) end."
I have looked at peoples answers but they all include the further parts of the question. I want to keep it simple, after all if i cant do the first part then there's no hope. it seems easy.
function range(start, end) {
let array = [];
for (let i = start; i <= end; i++){array.push(i);}
}
console.log(range(20 , 25));
but i get undefined, i have tried even copying and reducing the books answers to a similar situation.
It feels like my brain just cant do code. Where am i going wrong? Why is it undefined?
below is given answer
function range(start, end, step = start < end ? 1 : -1) {
let array = [];
if (step > 0) {
for (let i = start; i <= end; i += step) array.push(i);
} else {
for (let i = start; i >= end; i += step) array.push(i);
}
return array;
}
function sum(array) {
let total = 0;
for (let value of array) {
total += value;
}
return total;
}
console.log(range(1, 10))
// → [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(range(5, 2, -1));
// → [5, 4, 3, 2]
console.log(sum(range(1, 10)));
// → 55
thx guys
You are not returning anything from range. Use return array; in range function:
function range(start, end) {
let array = [];
for (let i = start; i <= end; i++){array.push(i);}
return array;
}
console.log(range(20 , 25));
The variable array is declared with let which gives it block scope. It is declared inside the function range
function range(start, end) {
let array = [];
for (let i = start; i <= end; i++){array.push(i);}
}
and its duration expires when the function terminates. It does not exist anymore afterwards.
As others have already said, return array.
This way a reference is kept for the line where it is called. And if assigned to another reference there, the duration of the array will be extended until unreferenced. Then it goes to garbage collection.
Example:
let arr = range(5,10);
the code for eloquent java script can be like this:
function range(start,end,step){
let myArr=[];
if(step){
for(let i=start;i<=end;i+=step){
myArr.push(i);
}
return myArr;
}
else{
for(let i=start;i<=end;i++){
myArr.push(i);
}
return myArr;}
}
function sum(arr){
let total=0;
for (let item of arr){
total +=item;
}
return total;
}
sum(range(1,10,2));

store every digit of a number in a arr by using a recursive function

I am trying to write a function to save all the digits of any given number in an array by using the recursive method, but it stops at the first digit and the looping is no work, can someone tell me what I did wrong?
function digit(n) {
var arr = [];
if (n < 10) {
return arr.push(n);
} else {
var dig = n % 10;
arr.push(dig);
digit(Math.floor(n / 10));
}
return arr;
}
Because you reset arr to an empty array each time, it never gets anywhere. You need to store it outside the recursive function and return it at the end.
function digit(d) {
var arr = [];
function store_digit(n) {
if (n < 10) {
return arr.push(n);
} else {
var dig = n % 10;
arr.push(dig);
store_digit(Math.floor(n / 10));
}
}
store_digit(d);
console.log(arr)
return arr;
}
digit(682)
The code is running through all the digits. Since you are initializing the array each time your function runs, it's just returning the last run digit.
Try this one:
var arr = [];
function digit(n) {
if (n < 10) {
return arr.push(n);
}
else {
var dig = n % 10;
arr.push(dig);
digit(Math.floor(n / 10));
}
}
digit(123456789)
console.log(arr)
recursion is correct but you are not using the returned values correctly, you will only return the last digit the way you are doing, you need to concat arrays returned from the successive method calls. something like this seems to work:
function digit(n){
var arr = [];
if(n<10){
arr.push(n);
}else{
var dig = n % 10;
arr.push(dig);
arr = arr.concat(digit(Math.floor(n /10)));
}
return arr;
}
console.log(digit(999));
digit(123456);
function digit(n) {
var arr = [];
if (n < 10) {
arr.push(n);
} else {
numberToString = n.toString();
for (var i = 0, len = numberToString.length; i < len; i += 1) {
arr.push(+numberToString.charAt(i));
}
console.log(arr);
}
}
All the answers given so far have got the right idea. Here's that idea expressed a little more simply:
function digits(n, result=[]){
return n < 10
? result.concat([n]).reverse()
: digits(Math.floor(n / 10), result.concat([n % 10]);
}
digits(1234); //=> [1, 2, 3, 4]
You can remove the .reverse() if the expected output goes smallest order to greatest order rather than greatest to smallest.
demo
You could use a clean approach, where every call of the function returns a valid part result.
At start you define the recursion temination, which is given if the value of n is smaller than 10. In this case you return an array with the value.
In all other cases, you return the result of the recursion call of the integer value of n divided by 10 and concat the rest of a division by 10.
This proposal does not use another explicit temporary variable.
function getDigits(n) {
if (n < 10) {
return [n];
}
return getDigits(Math.floor(n / 10)).concat(n % 10);
}
console.log(getDigits(123456));
For a more concise style, you could use a ternary with the same idea as above.
function getDigits(n) {
return n < 10 ? [n] : getDigits(Math.floor(n / 10)).concat(n % 10);
}
console.log(getDigits(123456));
Using the spread operator:
function getDigits(num, radix = 10) {
return num < radix ?
[num] :
[...getDigits(Math.floor(num / radix), radix), (num % radix)];
}
getDigits(0xCAFEBABE, 0x10);
// ==> [12, 10, 15, 14, 11, 10, 11, 14]
Code:
var arr = [];
function digit(n){
if (n<10) {
return arr.push(n);
} else {
var dig = n % 10;
arr.push(dig);
digit(Math.floor(n /10));
}
return arr;
}

Categories

Resources