// you’re reading...
1 Star2 Stars3 Stars4 Stars5 Stars (18 votes, average: 4.78 out of 5)
Loading...

Project Euler Solutions

Project Euler 92 Solution

Project Euler 92 Solution

Project Euler 92: Investigating a square of the digits number chain with a surprising property


Project Euler 92 Problem Description

Project Euler 92: A number chain is created by continuously adding the square of the digits in a number to form a new number until it has been seen before.

For example,

44 → 32 → 13 → 10 → 11
85 → 89 → 145 → 42 → 20 → 4 → 16 → 37 → 58 → 89

Therefore any chain that arrives at 1 or 89 will become stuck in an endless loop. What is most amazing is that EVERY starting number will eventually arrive at 1 or 89.

How many starting numbers below ten million will arrive at 89?

Analysis

Project Euler 92: To begin, all chains that end in 1 are called happy numbers. Any chain that contains 89 or 4 will be destined to an endless loop of calculations and forever remain unhappy. Here’s more information from Wikipedia: Happy number

It would seem a simple task to loop through all 107 numbers, calculate a chain for each one and count those that reach 89 or 4. This can, in fact, be done in less than a minute, but falls short for trying a limit of 1099 instead.

So, several optimizations can be ferreted out quickly when you realize that there are only 495 possible ways a number from 1 – 107 can have it’s digits squared and summed. The range for these numbers is 1 to 567 (92 * 7).

This means that any number in the target range of 1 – 107 can be looked up from a small table that determines ahead of time which number will be happy or not. By extension, as we learned from Kristian’s excellent Math Blog is to take similar “digited” numbers and simply add the multinomial coefficient to include all permutations of that number.

For example, 424501 is the same result of the sum of the square of the digits as is 244501, 501244, (0)12445, etc. In fact there are a total of 2520 combinations instead of 5040:

\frac{7!}{1! 1! 1! 2!} = 2520

If we only check 576 numbers and calculate the multinomial coefficient instead of adding 1 by checking all 10,000,000 we save many iterations and are able to calculate much more challenging limits, especially 1099.

This problem was solved using these ideas and dynamic programming in logarithmic time.

h_mark_sm-05bceb881aa02b72d688d21db01df5d8
This program and method
solves all test cases
on HackerRank

Project Euler 92 Solution

Runs < 0.010 seconds in Python 2.7.

download arrowUse this link to get the Project Euler 92 Solution Python 2.7 source.

Afterthoughts

    No afterthoughts yet.

Less then 2 secs to calculate 10^99:
848621012961290009929016807175952691990221212867104144408323613154869710\
828195585404753698625209870

Afterthoughts

    No afterthoughts yet.

Project Euler 92 Solution last updated

Discussion

6 Responses to “Project Euler 92 Solution”

  1. Enjoy and learned so much from this site. Please keep on posting! Thank you, Judy

    Posted by Judy | September 10, 2017, 11:22 AM
  2. “So, several optimizations can be ferreted out quickly when you realize that there are only 495 possible ways a number from 1 – 107 can have it’s digits squared and summed. The range for these numbers is 1 to 567 (92 * 7).”

    How did you reach these conclusions? Could you explain how you reached these numbers?

    Posted by Wayfaring Stranger | January 5, 2014, 10:14 PM
    • First, happy new year! Second, thanks for asking this question.

      Ok, if we ran this program:

      from Euler import sos_digits
      
      n = {sos_digits(x) for x in range(1,10000000)}
      print len(n), min(n), max(n)
      

      We’d get: 495 1 567
      This is the length of the set of unique sum of digits squared, the minimum and maximum of that set.
      1 is the minimum because the smallest sum of digits squared comes from the fist number in our list: 1.
      567 is the largest sum of digits squared for the largest 7 digit number, namely, 9,999,999, which is 9^2 * 7 or 567.

      Posted by Dreamer | January 6, 2014, 11:49 AM
  3. Hi,

    I’m wondering if you are posting more solutions. I really like your site and appreciate your contribution to those who want to learn more stuff about simple and efficient programming, like me.

    There is one improvement you can make about this problem.

    you used string integer casting in your program. It really takes time to run.

    def calc(n):
        s=0
        while n:
            s+=(n%10)**2
            n=n//10
        return s
    

    use a function like above instead of using n = sum(int(t)**2 for t in str(i)) can really shorten the time it costs.

    Thanks,

    Po

    Posted by Po | February 11, 2012, 5:43 AM
    • Hi Po,

      Yeah, I have to post more. I started this because projecteuler closed the comments section for older problems. They have since corrected that bad decision. But now that I have the momentum I think I’ll post more often.

      Thanks for your comment and suggestion to this solution. I will incorporate the changes and give you credit for making it better.

      Mike

      Posted by Mike | February 23, 2012, 1:19 PM

Post a comment