|
1 |
| -/* |
2 |
| -Factorial digit sum |
| 1 | +/** |
| 2 | + * Problem 20 - Factorial digit sum |
| 3 | + * |
| 4 | + * @see {@link https://projecteuler.net/problem=20} |
| 5 | + * |
| 6 | + * n! means n × (n − 1) × ... × 3 × 2 × 1 |
| 7 | + * |
| 8 | + * For example, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800, |
| 9 | + * and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27 |
| 10 | + * |
| 11 | + * Find the sum of the digits in the number 100! |
| 12 | + */ |
3 | 13 |
|
4 |
| -n! means n × (n − 1) × ... × 3 × 2 × 1 |
| 14 | +const factorialDigitSum = (n = 100) => { |
| 15 | + // Consider each digit*10^exp separately, right-to-left ([units, tens, ...]). |
| 16 | + const digits = [1] |
5 | 17 |
|
6 |
| -For example, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800, |
7 |
| -and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27. |
| 18 | + for (let x = 2; x <= n; x++) { |
| 19 | + let carry = 0 |
| 20 | + for (let exp = 0; exp < digits.length; exp++) { |
| 21 | + const prod = digits[exp] * x + carry |
| 22 | + carry = Math.floor(prod / 10) |
| 23 | + digits[exp] = prod % 10 |
| 24 | + } |
| 25 | + while (carry > 0) { |
| 26 | + digits.push(carry % 10) |
| 27 | + carry = Math.floor(carry / 10) |
| 28 | + } |
| 29 | + } |
8 | 30 |
|
9 |
| -Find the sum of the digits in the number 100! |
10 |
| -*/ |
| 31 | + // (digits are reversed but we only want the sum so it doesn't matter) |
11 | 32 |
|
12 |
| -const findFactorialDigitSum = (num) => { |
13 |
| - let result = 0 |
14 |
| - const stringifiedNumber = factorize(num).toLocaleString('fullwide', { useGrouping: false }) |
15 |
| - stringifiedNumber.split('').map(num => { result += Number(num) }) |
16 |
| - return result |
| 33 | + return digits.reduce((prev, current) => prev + current, 0) |
17 | 34 | }
|
18 | 35 |
|
19 |
| -const factorize = (num) => num === 0 ? 1 : num * factorize(num - 1) |
20 |
| - |
21 |
| -console.log(findFactorialDigitSum(100)) |
| 36 | +export { factorialDigitSum } |
0 commit comments