Have you ever come across a number that seems to hide a mathematical secret within its own structure? 🕵️♀️ Today we unravel one of those mysteries, exploring the fascinating Kaprekar numbers.
🔮 Problem Statement
The challenge is to determine if a given integer is a Kaprekar number. A number n is a Kaprekar number if, when squared and the result (as a string) is divided into two parts (left and right), the sum of those parts is equal to the original number n.
Parameters:
int n
: The number to evaluate.
Returns:
string
:"YES"
if the number is a Kaprekar number,"NO"
otherwise.
Example:
>>> is_kaprekar(9)
'YES'
>>> is_kaprekar(1)
'YES'
>>> is_kaprekar(99)
'YES'
>>> is_kaprekar(11)
'NO'
Additional Notes:
- If the square of the number has an odd number of digits, the “left” part may be shorter than the “right” part.
- Numbers are treated as strings to facilitate division.
🧩 Step-by-Step Solution
The key to solving this problem lies in breaking down the square of the original number into two parts and verifying if the sum of these parts matches the initial number. Here’s a detailed breakdown of each step:
First, we calculate the square of the number n
and convert it to a string. This conversion is crucial because it allows us to manipulate the number as a sequence of characters and divide it easily.
squared = str(pow(n, 2))
Next, we need to find the midpoint of the resulting string. This will help us separate the string into two parts (left and right). We use integer division (//
) to ensure we get an integer index, even if the length of the string is odd.
l = len(squared) // 2
The next step involves extracting the two parts of the string. This is where ternary operators come into play to handle special cases, such as when one of the parts is empty. If the left part of the string is empty, we assign 0
to the variable x
; otherwise, we convert the substring to an integer.
x = 0 if not squared[:l] else int(squared[:l])
We repeat a similar process for the right part of the string. Again, we use a ternary operator to handle the case where the right part is empty. If the right part of the string is empty, we assign 0
to the variable y
; otherwise, we convert the substring to an integer.
y = 0 if not squared[l:] else int(squared[l:])
Finally, we add the two parts converted to integers and compare the result with the original number n
. We return "YES"
if they match, indicating that n
is a Kaprekar number, and "NO"
otherwise.
return 'YES' if n == x + y else 'NO'
Here is the complete solution:
def is_kaprekar(n):
"level: medium; points: 5"
squared = str(pow(n, 2))
l = len(squared) // 2
x = 0 if not squared[:l] else int(squared[:l])
y = 0 if not squared[l:] else int(squared[l:])
return 'YES' if n == x + y else 'NO'
🧠 Key Concepts
String slicing is fundamental. It allows us to extract specific portions of the string representing the square of the number. Instead of resorting to loops or more complex functions, slicing provides a concise and efficient way to manipulate strings and obtain the necessary substrings to perform the calculations.
Ternary operators simplify the handling of edge cases. Their use allows us to express conditionals in a compact and readable way, avoiding the need to write more extensive if/else
blocks. In this case, the ternary operators are crucial for handling situations where one half of the square of the number is an empty string.
Type conversion is essential for operating with the data correctly. Initially, the square of the number is calculated as an integer, but then it is converted to a string to facilitate division into parts. Finally, the parts are converted back to integers to perform the sum. This flexibility in type conversion is key to manipulating the data effectively and performing the necessary operations.
Integer division (//
) ensures that the division index is always an integer, even when the length of the string is odd.
💫 Final Thoughts
This solution is efficient and concise, but we could optimize it further if we consider that the maximum input value is bounded. We could use a precalculated table of Kaprekar numbers to perform a direct lookup, although this would sacrifice the elegance of the original algorithm. ✨
Did you know that the number 297 is a Kaprekar number in base 10, but it is also one in base 16 (where it is written as 129)? Mathematics never ceases to amaze us! 🤯
I hope this journey through Kaprekar numbers has been as intriguing for you as it was for me. I invite you to explore more algorithms and mathematical challenges! Don’t forget that each line of code is an opportunity to learn and discover something new. Happy coding! 💻