4

I have an array of numbers e.g. [2, 4, 5] and must get the factorials in a new array. E.g. [2, 24, 120]

I am using .map as you can see to perform the function on each integer in the array however, this does not work? I assume something is wrong with the recursive function?

Thanks.

function getFactorials(nums) {

if(nums > 1){
    factarr = nums.map(x => x * (nums - 1));
}

return factarr;
}
SirNail
  • 85
  • 1
  • 8

7 Answers7

7

You could take a function for the factorial and map the values.

The function has a recusive style with a check for the value. if the value is zero, then the function exits with one. Otherwise it returnd the product of the actual value and the result of the call of the function with decremented value.

The check uses an implict casting of a falsy to a boolean value for the conditional (ternary) operator ?:.

const fact = n => n ? n * fact(n - 1) : 1;

var array = [2, 4, 5],
    result = array.map(fact);

console.log(result);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • thank you! i will try this. did not think to separate them :) – SirNail Aug 12 '19 at 12:06
  • this worked :) can you explain a little more on what is happening on the first line though? that would be appreciated – SirNail Aug 12 '19 at 12:07
  • @Tony `fact` is a function whose signature accepts an argument (n). If (n) is truthy (hence, if it's not 0, in your particular scenario), it returns n multiplied by fact(n - 1), otherwise it returns 1. Basically, it returns n * fact(n-1) recursively until n is not truthy anymore. – briosheje Aug 12 '19 at 12:16
  • @Nina_Scholz The ternary operator should have this condition `const fact = n => (n > 1) ? n * fact(n - 1) : 1;` or else It may throw `StackOverlow` for negative numbers :) – Vedant Terkar Aug 14 '19 at 10:33
  • 1
    @VedantTerkar, [`factorial`](https://en.wikipedia.org/wiki/Factorial) is only defined for positive integer numbers. – Nina Scholz Aug 14 '19 at 10:50
1

Just create a function that calculates the factorial of a given number then just use it as the callback for the map function.

As the main part is the way to calculate the factoriel, here's two manners to do that task

Factoriel function iterative way :

const fact = n => {
  let f = 1,
  i = n;
  for(; i > 1; i--) f *= i;
  return f;
};

console.log(fact(4)); /** outpuut: 24 **/

Factoriel function recursive way :

const fact = n => n > 1 ? n * fact(n - 1) : n;

console.log(fact(4)); /** outpuut: 24 **/

And the final code :

const arr = [2, 4, 5],
  fact = n => n > 1 ? n * fact(n - 1) : n,
  factArr = arr.map(i => fact(i));

console.log(factArr); /** output: [2, 24, 120] **/
ThS
  • 4,597
  • 2
  • 15
  • 27
0

You are doing the recursion wrong, my approach would be to define the factorial calculator as a separate function:

function getFactorials(nums) {
  function factorial(n){
    return n === 0 ? 1 : n * factorial(n - 1);
  }
  return nums.map(x => factorial(x));
}
console.log(getFactorials([0, 1, 2, 3, 4, 5 ,6]));
Fullstack Guy
  • 16,368
  • 3
  • 29
  • 44
0

You need to calculate each factorial in array, your current code is not doing that. Consider following example:

function factorial(num) {
    if (num === 0 || num === 1) {
    return 1;
  } else {
    return num * factorial(num - 1);
  }
}

const facts = [2, 4, 5];
const factsArr = facts.map(num => factorial(num));

In you code you was just multiplying each member of array by array itself.

Furman
  • 2,017
  • 3
  • 25
  • 43
0

Instead of doing it recursively, I took the solution from @Amin Jafari which uses reduce(). This function is quicker than the recursive solution.

First we generate an array. We do so by using Array(n + 1). n is the factorial so e.g. for 6! our n would be 6. We get the indices with keys() but Array() by itself only returns a truly empty array and keys() only returns an iterator. So we spread it and put the result of that into a new array. Thus, we have e.g. [0,1,2,3,4,5,6] (for n + 1 with n = 6). We exclude the 0 with slice(1).

Afterwards we finally apply reduce. Reduce iterates over all elements, applies a function while keeping track of an accumulator. Our accumulator here is the current product. So what happens is that 1 * 2 gets calculated and the result saved in a, our accumulator. Then we multiply a with the next value, so 2 * 2* and this happens until we went through our whole self generated array.

This function based on reduce we can then use to transform each value in our original array with map().

const factorial = n => [...Array(n+1).keys()].slice(1).reduce((a,c) => a * c),
      data = [2, 4, 5];

let res = data.map(v => factorial(v));

console.log(res);
claasic
  • 1,050
  • 6
  • 14
0

I know that this post has a lot of answers already, but I might have something to add:

If you are planning to use the recursive function a lot to calculate factorials, let's say you need this in a browser game every .5 secs, you will notice that it is consuming a lot of resources, mainly your time .

My proposition is:

  • calculate the factorials once
  • store them in the app state
  • look them up instead of calculating them

example code (based on Nina Scholz's anwer):

// create this earlier, put it in the application state
const state = {lookupFact: []}

const fact = n => n ? n * fact(n - 1) : 1;

// only calculate the factorials once
function lookupFact(par) {
  if (state.lookupFact.length == 0) {
    for (var i = 0; i <= 170; i++) {
      state.lookupFact[i] = fact(i)
    }
  }
  return state.lookupFact[par]
}

// use it like this later on
console.log(lookupFact(1), lookupFact(10), lookupFact(5))

As I said, you should use this only if you have to calculate factorials all the time.

0
var arr = [2,3,4,5,6,7]

arr.map((value, ind) => {
  var facts = 1;
  for (value  ;value > 0 ;value--) {
    facts = facts *value;
  }
  console.log(facts);
})
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
  • 1
    Your answer could be improved by adding more information on what the code does and how it helps the OP. – Tyler2P Nov 05 '22 at 17:13