Today I challenged myself to compute a way to find if a number is happy or not.
So what is a happy number?
To quote the wikipedia page:
A happy number is defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits in base-ten, and repeat the process until the number either equals 1 (where it will stay), or it loops endlessly in a cycle that does not include 1. Those numbers for which this process ends in 1 are happy numbers, while those that do not end in 1 are unhappy numbers (or sad numbers).
Now that we know what a happy number is let's code !
Let's get a positive number from the user
For this part I will use:
input()
to get the input from the user.int()
to convert the output ofinput()
to integer.abs()
to return the absolute value of the given number.
def given_number():
"""
This function ask the user for a number and return it so it
can be usable by other functions.
Returns: int
The given number.
"""
# We use while because I want to infinite ask for a number
# if the user do not give us a number.
while True:
# because the use can input anything, I choosed to
# handle the exception if the user do not give us a
# number.
# This way we keep asking untill the user give us a
# number.
try:
initial_number = abs(int(input("Give us a number ")))
break
except ValueError:
continue
return initial_number
Spliting digits
Because to compute the happy numbers checking we have to calculate the sum of the square of its digits in base-ten. So, I choosed to directly split each digit of the sequence before doing the calculations.
For this part I will use:
int()
to convert each digits to integer.str()
to convert the given number to string.map()
to iterate through the converted string.
def split_digits(digits):
"""
This function split each digits of a given number.
Argument:
- digits: int
The number to split.
Returns: list
A list with each digit.
"""
# We convert the given number to string first.
# Then we the iterate over each characters which are
# converted as integer.
# As map return a list, and int replace the current
# iteration to integer, we get the list of each digits
# of the number.
return map(int, str(digits))
Calculation of the sum of the square of each digits
For this part I will use:
pow()
to calculate the square of each digits.
def calculation(digits):
"""
This function return the calculation of the sum of the square
of each digits.
Returns: int
The result of the recursively sum of squares of each
digits.
"""
# This variable is used to store the calculation results.
result = 0
# We use for to iterate through the list of digits given by
# split_digits().
for digit in digits:
# We append the square of the current digits to result
# this way we can return the results once we finished
# to iterate through the list of digits.
result += pow(digit, 2)
return result
Is a number happy ?
Because I wanted to be eable to check if a number is happy from another script, I choosed to write a function which will tell us if a number is happy (True
) or unhappy (False
).
As I also want to see the sequence of the results of calculation()
when I will work with this function, I introduced between everything a switch which if True
will give us a tuple of (True, [results of calculation()])
if the number is happy and (False, [results of calculation()])
if the number is unhappy.
Finally please note that as I did not want to wait for an endless loop, I choosed to check if the result of calculation()
was already in our list of results. If it is the case then we have an unhappy number.
For this part I will use:
split_digits()
calculation()
list.append()
to append an element to our list of results.
def is_happy(number, return_sequence=False):
"""
This function check if a number is happy or not.
Argument:
- number: int
The number to check.
- return_sequence: bool
If True we return the sequence of results.
Returns: bool or tuple
- True: number is happy.
- False: number is unhappy.
- tuple: if return_sequence == True
- We return (True|False, past_results)
"""
# This will save the list of previous or past results.
past_results = []
list_of_digits = split_digits(number)
# I choosed to to an endless loop because we do not know
# where we are going and which path to choose.
while True:
current_result = calculation(list_of_digits)
if current_result not in past_results:
if current_result != 1:
list_of_digits = split_digits(current_result)
past_results.append(current_result)
elif return_sequence:
return (True, past_results)
return True
elif return_sequence:
return (False, past_results)
return False
What if we want to run the scripts ?
Well, to run it as a script with for example python happy_number.py
I added the following to the script.
Please note the usage of if __name__ == '__main__':
which avoid the script running when we are exporting for example is_happy()
for another script or module.
Is this part I will use:
__name__
to check if the script is not imported from anoter one.given_number()
is_happy()
print()
to print on screen the information about the number.
if __name__ == '__main__':
NUMBER = given_number()
if is_happy(NUMBER):
print('%d is a happy number' % NUMBER)
else:
print('%d is an unhappy number' % NUMBER)