1
\$\begingroup\$

145 is a curious number, as 1! + 4! + 5! = 1 + 24 + 120 = 145.

Find the sum of all numbers which are equal to the sum of the factorial of their digits.

Note: as 1! = 1 and 2! = 2 are not sums they are not included.

from time import time


def fact(n):
    """returns factorial of n."""
    total = 1
    for number in range(2, n + 1):
        total *= number
    return total


def fact_curious(n, factorials={1:1, 2:2}):
    """Assumes n is the range to check for curious numbers.
    generates curious numbers within n range."""
    for number in range(3, n):
        try:
            if sum(factorials[int(digit)] for digit in str(number)) == number:
                yield number
        except KeyError:
            for digit in str(number):
                factorials[int(digit)] = fact(int(digit))
            if sum(factorials[int(digit)] for digit in str(number)) == number:
                yield number


if __name__ == '__main__':
    start_time1 = time()
    print(sum(fact_curious(100000)))
    print(f'Time: {time() - start_time1}')
\$\endgroup\$
  • 3
    \$\begingroup\$ Please tag all Python questions with python, if you only have python-3.x then your question is more likely to go unanswered. \$\endgroup\$ – Peilonrayz Jul 21 at 6:49
1
\$\begingroup\$
  1. There is math.factorial function. So no need to reinvent it.
  2. Using try/except for control flow is a bad practice. It's better to explicitly check whether a list contains a value using the condition if int(digit) in factorials. It also will eliminate the code duplication in except branch.
  3. It's even better to pre-calculate all factorials for digits from 0 to 9. Anyway, you will reuse them all a lot of times.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy