Discovering Happy Numbers Between 1 and 100 in Python

Rate this post

πŸ’‘ Problem Formulation: We seek to find all “happy numbers” between 1 and 100 using Python programming. A happy number is defined as a number that eventually reaches 1 when replaced by the sum of the square of each digit. For instance, if we start with 19, the sequence is 1Β² + 9Β² = 82, then 8Β² + 2Β² = 68, then 6Β² + 8Β² = 100, and finally 1Β² + 0Β² + 0Β² = 1, making 19 a happy number. The desired output is a list of numbers between 1 and 100 that are happy.

Method 1: Iterative Approach

An iterative approach to finding happy numbers involves calculating the sum of squares of digits repeatedly until you either reach 1 (happy number) or fall into a loop that does not include 1 (unhappy number). This method is straightforward and demonstrates the basic algorithm clearly.

Here’s an example:

def is_happy(number):
    cycle = set()
    while number != 1 and number not in cycle:
        cycle.add(number)
        number = sum(int(i)**2 for i in str(number))
    return number == 1

happy_numbers = [num for num in range(1, 101) if is_happy(num)]
print(happy_numbers)

Output:

[1, 7, 10, 13, 19, 23, 28, 31, 32, 44, 49, 68, 70, 79, 82, 86, 91, 94, 97, 100]

This code snippet defines a function is_happy() that determines whether a number is happy. It uses a set to keep track of all the numbers seen during the cycle to detect loops. The list comprehension then checks every number between 1 and 100, keeping only the happy ones, which are printed at the end.

Method 2: Recursive Approach

In the recursive approach, we define a recursive function that calculates the sum of the squares of its digits until the result is either 1 or it repeats a previously seen value. This method elegantly harnesses the power of recursion to simplify the code logic.

Here’s an example:

def is_happy_recursive(number, cycle=None):
    if cycle is None:
        cycle = set()
    if number == 1:
        return True
    if number in cycle:
        return False
    cycle.add(number)
    return is_happy_recursive(sum(int(i)**2 for i in str(number)), cycle)

happy_numbers = [num for num in range(1, 101) if is_happy_recursive(num)]
print(happy_numbers)

Output is the same list of happy numbers as in Method 1.

This snippet introduces the is_happy_recursive() function which calls itself to determine if a number is happy. The stopping conditions are when the number becomes 1 (happy) or is already in the cycle (unhappy). It’s a clean, recursive counterpart to the iterative approach.

Method 3: Using a Pre-calculated Hash

A pre-calculated hash method involves storing previously computed happy numbers in a hash or set to optimize calculations. It avoids recalculating for numbers that are already known to be happy or unhappy, significantly reducing execution time.

Here’s an example:

known_happies = set()

def is_happy_hash(number):
    original_number = number
    cycle = set()
    while number != 1 and number not in cycle:
        if number in known_happies:
            known_happies.add(original_number)
            return True
        cycle.add(number)
        number = sum(int(i)**2 for i in str(number))
    if number == 1:
        known_happies.update(cycle)
        known_happies.add(original_number)
    return number == 1

happy_numbers = [num for num in range(1, 101) if is_happy_hash(num)]
print(happy_numbers)

The function is_happy_hash() benefits from the known_happies set that stores every happy number found to quicken future checks. As each happy number is identified, it and its cycle members are added to the set for improved efficiency.

Method 4: Functional Programming with map and filter

Embracing a functional programming style, we can use map and filter functions to apply the happy number condition to the range of numbers and filter out the happy ones. This method showcases Python’s functional programming capabilities while keeping the code concise and readable.

Here’s an example:

list(filter(is_happy, map(int, range(1, 101))))

Assuming is_happy is the same function we discussed earlier, this one-liner code snippet filters out the happy numbers between 1 and 100 using a functional programming pattern, which looks elegant and concise.

Bonus One-Liner Method 5: Using a Generator Expression

For those who appreciate Python’s compact expression capabilities, we can use a generator expression alongside our happy number checking function. This offers an efficient and Pythonic way to achieve our goal in just one line of code.

Here’s an example:

print([num for num in range(1, 101) if is_happy(num)])

The output will be the same list of happy numbers as before. This method takes advantage of Python’s list comprehensions and generator expressions for a slick, one-line solution.

Summary/Discussion

  • Method 1: Iterative Approach. Simple and straightforward implementation. May become slow if not optimized properly as the range of numbers increases.
  • Method 2: Recursive Approach. Elegant and concise, showcasing recursion. Can hit Python’s recursion limit for large numbers or complex recursion trees.
  • Method 3: Pre-calculated Hash. Fast for large datasets by reusing previous results. Requires memory to store known results, which could become significant with larger ranges of numbers.
  • Method 4: Functional Programming. Clean and expressive code leveraging Python’s functional programming features. May be less intuitive for those unfamiliar with functional programming concepts.
  • Method 5: Generator Expression. Highly Pythonic one-liner. It may be less clear to beginners but is very efficient in terms of memory usage.