Tuesday 26 June 2018

Happy Numbers

Today I turned 25286 days old and 25286 happens to be a happy number, defined as:
Let us define a function \( s(n) \), for \( n>0 \), which gives the sum of the squares of the digits of \( n \), so, for example, \( s(37)=3^2+7^2=58 \).

If we start from a number \(n\)  and we repeatedly apply \( s(\cdot) \), we obtain a sequence \(S_n\) of numbers \(n\), \(s(n) \), \(s(s(n)\), \(\dots \), and so on.

A number \(n\) is called happy if \(S_n \) contains the number 1.

Note that \(s(1)=1 \), so in that case the sequence \( S_n \) has an infinite tail of \(1\)'s.

If a number is not happy then it is easy to see that at a certain point \(S_n\) will enter the infinite loop$$ \dots,4, 16, 37, 58, 89, 145, 42, 20, 4,\dots $$So, for example, starting from  \(94\)  we obtain \(94\rightarrow97\rightarrow130\rightarrow10\rightarrow1\), so \(94\) is happy. 

On the contrary, starting from 61 we obtain \(61\rightarrow37\rightarrow58\rightarrow89 \) and thus 61 is not happy, since 89 belongs to the unhappy loop.

According to Wikipedia
by inspection of the first million or so happy numbers, it appears they have a natural density of around 0.15. Perhaps surprisingly, then, the happy numbers do not have an asymptotic density. The upper density of the happy numbers is greater than 0.18577, and the lower density is less than 0.1138. After 25286, the next happy number is 25294 (followed by 25295).
As usual I tried to write some SAGE code to determine whether a number was happy or not. Here is what I came up with:
INPUT (using a happy number 25286):
entered_number=25286
number=str(entered_number)
while sum!= 1 and sum!=4:
    sum=0
    for x in range(len(number)):
        sum+=Integer(number[x])^2
    number=str(sum)
    print(sum) 
OUTPUT
133
19
82
68
100
1
INPUT (using an unhappy number 89)
entered_number=89
number=str(entered_number)
while sum!= 1 and sum!=4:
    sum=0
    for x in range(len(number)):
        sum+=Integer(number[x])^2
    number=str(sum)
    print(sum) 
OUTPUT
145
42
20
4
The 4 is used to prevent the program going into an infinite loop and, at the same time, to mark a number as happy. Unhappy numbers will always enter the following loop:

... 4, 16, 37, 58, 89, 145, 42, 20, 4, ...

Any of the above numbers could be used to identify an unhappy number and break the loop.

The Wikipedia article on unhappy numbers includes the following Python code for determining whether a number is happy or unhappy (rather than displaying the trajectory as I did in my SAGE program):
INPUT (using happy number 25286)
def square(x):
    return int(x) * int(x)
def happy(number):
    return sum(map(square, list(str(number))))
def is_happy(number):
    seen_numbers = set()
    while number > 1 and (number not in seen_numbers):
        seen_numbers.add(number)
        number = happy(number)
    return number == 1
is_happy(25286) 
OUTPUT
True
INPUT (using unhappy number 89)
def square(x):
    return int(x) * int(x)
def happy(number):
    return sum(map(square, list(str(number))))
def is_happy(number):
    seen_numbers = set()
    while number > 1 and (number not in seen_numbers):
        seen_numbers.add(number)
        number = happy(number)
    return number == 1
is_happy(89) 
OUTPUT
False 
As can be seen, the Python code involves a quite different approach. It defines three functions, the second building on the first and the third building on the second : square(x), happy(number) and is_happy(number).

The command sum(map(square, list(str(number)))) caught my eye. This is a very useful command that takes two inputs:
  • a function (in this case, square)
  • a list (in this case, str(number))
It outputs a list (in this case, the sum of the number's digits squared).

No comments:

Post a Comment