2

Now, we have this recursive function:

function digitsMultipication(number) {
  let strNumber = number.toString();
  let firstNum = parseInt(strNumber[0]);

  if(strNumber.length==1){
    return firstNum
  }else{
    let x = ''
    for(i=1;i<strNumber.length;i++){
        x += strNumber[i]
    }
    x = parseInt(x)
    return firstNum * digitsMultipication(x);
  }
}

// TEST CASES
console.log(digitsMultipication(66)); // 36

How do we edit this function since we want the output condition is literally one digit. Because 36 is still 2 digits and we want the function recursed again until the output is one digit, which is 8.

66 => 6 * 6 = 36,
36 => 3 * 6 = 18,
18 => 1 * 8 = 8 (the wanted final output)

customcommander
  • 17,580
  • 5
  • 58
  • 84
ratavagn
  • 77
  • 1
  • 6
  • Multiply the first digit of the string by the `digitsMultiplication` of the rest of the string. For example, `result("1234") = 1 * result("234") = 1 * 2 * result("34")`, and so on. Your "base case" will be when you only have 2 or fewer remaining digits. – byxor Jan 22 '20 at 17:47
  • What I understand from your explanation is that the final result is 24 (1*2*3*4). But what we wanted is the function recursed again until it has one digit result. So, the final result should be 8 (2*4). Because 24 is still 2 digits – ratavagn Jan 22 '20 at 17:54
  • Check [this](https://stackoverflow.com/q/59570841/1244884) out. – customcommander Jan 22 '20 at 19:57

2 Answers2

2

Did you mean something like that?

const
  get = num => {
      const sum = [...num + ''].reduce((sum, n) => n * sum);
      return sum < 10 ? sum : get(sum);
  },
  result = get(66);

console.log(result);

A more effective way is to avoid stringify, and use only math:

const
  get = num => {
      let sum = 1;
      
      while (num) {
        sum *= num % 10;
        num = parseInt(num / 10);
      }
      
      return sum < 10 ? sum : get(sum);
  },
  result = get(66);

console.log(result);

And even save memory and avoid recursion:

const
  get = num => {
    let sum = 1;

    for (;;) {
      sum *= num % 10;
      num = parseInt(num / 10);

      if (num <= 0) {
        if (sum < 10) return sum;

        num = sum;
        sum = 1;
      }
    }
  },
  result = get(66);
  
console.log(result);
Nave Sade
  • 441
  • 2
  • 6
  • Yup correct! But I can't understand your idea. You can explain the idea to us to make it clearer if you don't mind – ratavagn Jan 22 '20 at 18:29
  • 2
    @AndersonPimentel Sure. To convert a number to an array, you can use the ```toString``` function, but you can just added the number to a string, it will already automatically converted. Then, to convert a string to an array, you can use one of the ```Array.from``` or ```split('')``` functions, but you can simply destruct the string using a spread operator. To me it is more elegant. That's it. – Nave Sade Jan 22 '20 at 18:33
  • 2
    @AndersonPimentel num is 66. `+''` converts it to string. spread operator `...num` converts it to `['6','6']` – TheWandererLee Jan 22 '20 at 18:35
  • 1
    @ratavagn I convert the number to a string so that I can easily access the numbers it consists of, one by one. I multiply them one by the other (using ```reduce```), and then - if the sum is less than 10 (and therefore single digit) - I return it, and if not I continue for another round. – Nave Sade Jan 22 '20 at 18:38
  • `[...num + ''].reduce((sum, n) => Number(n) * sum)` - This won't work for negative numbers. You also don't need to use `Number()` since the multiplication will coerce both operands to numbers anyway. – customcommander Jan 22 '20 at 20:01
  • @customcommander You right but negative numbers were not part of the requirement.. I answered the specific requirement he requested. And for negative numbers - my two additional solutions will work. As for the first, dashes can be taken away by ```[...Math.abs(num) + '']```. – Nave Sade Jan 23 '20 at 09:56
1

First let's write two simple functions:

  1. mult - multiples a and b

    const mult = (a, b) => a * b;
    
    mult(3, 4);
    //=> 12
    
  2. prod - multiplies together all the elements of a list.

    const prod = (...ns) => ns.reduce(mult);
    
    prod(1, 2, 3, 4);
    //=> 24
    

How can we split a number (we assume a positive integer) into its digits?
i.e. from 123 to [1, 2, 3]. There are many ways you can do this. For this answer I'll just use:

const to_digits = n => Array.from(String(n), Number);

to_digits(123);
//=> [1, 2, 3]

Now let's refactor your function (I called it prod_digits):

const prod_digits =
  n =>
      Math.abs(n) < 10  ? n
    : n < 0             ? prod_digits(prod(-1, ...to_digits(Math.abs(n))))
                        : prod_digits(prod(...to_digits(n)));
                        
                        
console.log(prod_digits(66));  //=> 8
console.log(prod_digits(-66)); //=> -8
console.log(prod_digits(6));   //=> 6
console.log(prod_digits(-6));  //=> -6
<script>
const to_digits = n => Array.from(String(n), Number);
const mult = (a, b) => a * b;
const prod = (...n) => n.reduce(mult);
</script>

Optimisation(s)

As an exercise, you could implement two early exit conditions:

  1. If to_digits returns a list that contains a 0, just returns 0
  2. If to_digits returns a list made up of only 1, just returns 1
customcommander
  • 17,580
  • 5
  • 58
  • 84
  • Why not use `Math.abs` unconditionally, and remove the branching around `n < 0`? If you want to continue the branching, then I think `- n` is cleaner than `Math.abs(n)`. – Scott Sauyet Jan 22 '20 at 21:38
  • 1
    @ScottSauyet Not sure what you mean exactly. I need the `n < 0` check to sneak in a `-1`in the `prod(...)` call so it returns a negative result. e.g. `-123` ~> `prod(-1, 1, 2, 3) === -6` – customcommander Jan 22 '20 at 21:43
  • Oh, right. I would prefer a positive sign on the "product of the digits". But if you want possible negative results, obviously you need something. Sorry about that. Still, another variant would be `n => Math.abs(n) < 10 ? n : prod_digits(prod(Math.sign(n), ...to_digits(Math.abs(n))))`, although that may not work in IE. – Scott Sauyet Jan 23 '20 at 14:24