¿Alguna vez te has topado con un número que parece esconder un secreto matemático en su propia estructura? 🕵️♀️ Hoy desentrañamos uno de esos misterios, explorando los fascinantes números de Kaprekar.
🔮 Enunciado del Problema
El desafío es determinar si un número entero dado es un número de Kaprekar. Un número n es un número de Kaprekar si, al elevarlo al cuadrado y dividir el resultado (como una cadena) en dos partes (izquierda y derecha), la suma de esas partes es igual al número original n.
Parámetros:
int n
: El número a evaluar.
Retorna:
string
:"SI"
si el número es un número de Kaprekar,"NO"
en caso contrario.
Ejemplo:
>>> is_kaprekar(9)
'SI'
>>> is_kaprekar(1)
'SI'
>>> is_kaprekar(99)
'SI'
>>> is_kaprekar(11)
'NO'
Notas Adicionales:
- Si el cuadrado del número tiene un número impar de dígitos, la parte “izquierda” puede ser más corta que la parte “derecha”.
- Los números se tratan como cadenas para facilitar la división.
🧩 Resolución Paso a Paso
La clave para resolver este problema reside en descomponer el cuadrado del número original en dos partes y verificar si la suma de estas partes coincide con el número inicial. Aquí te presento el desglose detallado de cada paso:
Primero, calculamos el cuadrado del número n
y lo convertimos en una cadena. Esta conversión es crucial porque nos permite manipular el número como una secuencia de caracteres y dividirlo fácilmente.
squared = str(pow(n, 2))
Luego, necesitamos encontrar el punto medio de la cadena resultante. Esto nos ayudará a separar la cadena en dos partes (izquierda y derecha). Usamos la división entera (//
) para asegurarnos de obtener un índice entero, incluso si la longitud de la cadena es impar.
l = len(squared) // 2
El siguiente paso implica extraer las dos partes de la cadena. Aquí es donde los operadores ternarios entran en juego para manejar casos especiales, como cuando una de las partes está vacía. Si la parte izquierda de la cadena está vacía, asignamos 0
a la variable x
; de lo contrario, convertimos la subcadena a un entero.
x = 0 if not squared[:l] else int(squared[:l])
Repetimos un proceso similar para la parte derecha de la cadena. De nuevo, usamos un operador ternario para manejar el caso en que la parte derecha está vacía. Si la parte derecha de la cadena está vacía, asignamos 0
a la variable y
; de lo contrario, convertimos la subcadena a un entero.
y = 0 if not squared[l:] else int(squared[l:])
Finalmente, sumamos las dos partes convertidas a enteros y comparamos el resultado con el número original n
. Retornamos "SI"
si coinciden, indicando que n
es un número de Kaprekar, y "NO"
en caso contrario.
return 'SI' if n == x + y else 'NO'
Aquí está la solución completa:
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 'SI' if n == x + y else 'NO'
🧠 Conceptos Clave
El slicing de cadenas es fundamental. Nos permite extraer porciones específicas de la cadena que representa el cuadrado del número. En lugar de recurrir a bucles o funciones más complejas, el slicing nos proporciona una forma concisa y eficiente de manipular las cadenas y obtener las subcadenas necesarias para realizar los cálculos.
Los operadores ternarios simplifican el manejo de casos borde. Su uso nos permite expresar condicionales de manera compacta y legible, evitando la necesidad de escribir bloques if/else
más extensos. En este caso, los operadores ternarios son cruciales para manejar situaciones donde una de las mitades del cuadrado del número sea una cadena vacía.
La conversión de tipos es esencial para operar con los datos correctamente. Inicialmente, el cuadrado del número se calcula como un entero, pero luego se convierte a una cadena para facilitar la división en partes. Finalmente, las partes se convierten de nuevo a enteros para realizar la suma. Esta flexibilidad en la conversión de tipos es clave para manipular los datos de manera efectiva y realizar las operaciones necesarias.
La división entera (//
) asegura que el índice de división sea siempre un entero, incluso cuando la longitud de la cadena es impar.
💫 Reflexiones Finales
Esta solución es eficiente y concisa, pero podríamos optimizarla aún más si consideramos que el valor máximo de entrada está acotado. Podríamos usar una tabla precalculada de números de Kaprekar para realizar una búsqueda directa, aunque esto sacrificaría la elegancia del algoritmo original. ✨
¿Sabías que el número 297 es un número de Kaprekar en base 10, pero también lo es en base 16 (donde se escribe como 129)? ¡La matemática nunca deja de sorprendernos! 🤯
Espero que este recorrido por los números de Kaprekar haya sido tan intrigante para ti como lo fue para mí. ¡Te invito a explorar más algoritmos y desafíos matemáticos! No olvides que cada línea de código es una oportunidad para aprender y descubrir algo nuevo. ¡Hasta la próxima, y feliz codificación! 💻