Cómo aprender a resolver algoritmos y Code Katas (sin frustrarte en el intento)
En algún momento probablemente escuchaste palabras como algoritmos o code katas en programación, y viste cientos de ejercicios donde el objetivo parece ser resolver problemas con la solución más eficiente posible.
Jose Gratereaux
Author
Muchos desarrolladores creen que resolver algoritmos es cuestión de “ser inteligente” o tener talento natural.
Pero la realidad es otra:
Resolver algoritmos es una habilidad entrenable.
Al igual que aprender un framework, escribir buen código o diseñar arquitectura, mejorar en code katas requiere práctica, estructura y una forma correcta de pensar.
La mayoría de las personas fallan no porque no sepan programar, sino porque intentan resolver el problema directamente sin entender cómo descomponerlo.
¿Qué es un Code Kata?
Un Code Kata es un ejercicio pequeño diseñado para practicar lógica y resolución de problemas.
La idea viene de las artes marciales: repetir ejercicios constantemente hasta desarrollar fluidez.
Sitios populares:
- Codewars
- LeetCode
- HackerRank
- Exercism
El error más común al resolver algoritmos
La mayoría hace esto:
- Lee el problema
- Intenta escribir código inmediatamente
- Se bloquea
- Busca la respuesta en Google
Ese flujo mata el aprendizaje.
La mentalidad correcta
Cuando resuelves algoritmos, NO estás programando primero.
Estás pensando primero.
Tu objetivo inicial NO es escribir código elegante.
Tu objetivo es:
- entender el problema
- dividirlo
- detectar patrones
- encontrar una estrategia
El código viene después.
Cómo afrontar un algoritmo correctamente
1. Entiende el problema completamente
Antes de escribir código, pregúntate:
¿Qué entra? ¿Qué debe salir? ¿Qué restricciones existen? ¿Qué casos especiales pueden ocurrir? ¿Qué pasa con valores vacíos? ¿Qué pasa con números negativos? ¿Qué pasa si el input es enorme? 2. Resuelve el problema manualmente
Esto es CRÍTICO.
Muchos quieren resolverlo en código sin antes resolverlo como humanos.
Ejemplo:
“Dado un string, retorna la cantidad de vocales.”
Antes del código:
"hello"
h -> no
e -> sí
l -> no
l -> no
o -> sí
resultado = 2
Cuando haces esto, tu cerebro comienza a detectar el patrón.
3. Divide el problema en pasos pequeños
Nunca pienses:
“¿Cómo resuelvo esto?”
Piensa:
“¿Qué pequeña acción debo hacer primero?”
Por ejemplo:
- recorrer el texto
- verificar si cada letra es vocal
- aumentar contador
- retornar resultado
Ahora el problema parece muchísimo más simple.
4. Escribe pseudocódigo
Antes de JavaScript:
crear contador
recorrer cada letra
si la letra es vocal
aumentar contador
retornar contador
Si puedes explicar la lógica en español simple, probablemente ya sabes resolverlo.
5. Ahora sí: escribe código
Aquí recién conviertes la lógica a JavaScript.
Ejemplo completo paso a paso
Vamos a resolver este problema:
Problema
Dado un array de números, retorna el número más grande.
Ejemplo:
findLargest([3, 7, 2, 9, 1])
// 9
Paso 1 — Entender el problema
Input:
[3, 7, 2, 9, 1]
Output:
9
Paso 2 — Resolverlo manualmente
¿Cómo lo haría un humano?
empiezo con 3
7 es mayor que 3
ahora el mayor es 7
2 no es mayor que 7
9 sí es mayor que 7
ahora el mayor es 9
1 no es mayor que 9
Patrón detectado:
- guardar el mayor actual
- comparar cada número
- actualizar cuando aparezca uno más grande
Paso 3 — Pseudocódigo
guardar primer número como mayor
recorrer el array
si el número actual es mayor que el mayor
actualizar mayor
retornar mayor
Paso 4 — Pasarlo a JavaScript
function findLargest(numbers) {
let largest = numbers[0];
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] > largest) {
largest = numbers[i];
}
}
return largest;
}
Paso 5 — Pensar como programador
Aquí viene la parte importante.
Cuando yo resuelvo este problema, mi cerebro piensa algo así:
Necesito comparar números.
Para comparar, debo recordar cuál es el más grande hasta ahora.
Entonces necesito una variable.
¿Cómo reviso todos los números?
Con un loop.
¿Qué hago dentro del loop?
Comparar el actual con el mayor.
Si encuentro uno mayor:
actualizo.
Eso es resolver algoritmos.
No es memorizar soluciones. Es entrenar tu capacidad de dividir problemas.
Cómo mejorar realmente en algoritmos
1. Haz problemas pequeños
Muchos empiezan con problemas extremadamente difíciles. Empieza con:
- strings
- arrays
- loops
- objetos
- contadores
- frequency counters
- two pointers
2. Repite problemas
Resolver un problema una vez NO crea habilidad. Rehacerlo sí.
Un buen ejercicio:
- resolver hoy
- repetir mañana sin mirar
- repetir en 1 semana
3. Aprende patrones
Los algoritmos parecen infinitos… pero no lo son.
Muchos problemas usan los mismos patrones:
- Sliding Window
- Two Pointers
- Hash Maps
- Recursion
- Stack
- Queue
- Binary Search
Cuando reconoces patrones, comienzas a resolver mucho más rápido.
4. NO memorices soluciones
Memorizar mata el aprendizaje.
En vez de memorizar:
pregúntate:
- ¿por qué funciona?
- ¿qué patrón usa?
- ¿cómo llegaría a esto desde cero?
5. Habla mientras resuelves
Esto ayuda muchísimo.
Literalmente habla:
ok…
necesito recorrer el array…
ahora debo comparar…
Eso obliga a tu cerebro a estructurar lógica.
6. Aprende a tolerar la frustración
Los algoritmos son incómodos.
Y eso es normal.
Parte del proceso es quedarse bloqueado.
La mejora ocurre precisamente ahí.
Un ejercicio excelente para practicar Problema
Retorna true si una palabra es palíndromo.
Ejemplos:
isPalindrome("ana") // true
isPalindrome("radar") // true
isPalindrome("hello") // false
Cómo pensarlo
Paso 1
¿Qué es un palíndromo?
Una palabra que se lee igual al derecho y al revés.
Paso 2
¿Cómo invierto una palabra?
Tal vez:
convertir en array
invertir
unir
Solución
function isPalindrome(word) {
const reversed = word.split("").reverse().join("");
return word === reversed;
}
Luego viene la evolución
Después puedes preguntarte:
- ¿Cómo hacerlo sin reverse()?
- ¿Cómo optimizar memoria?
- ¿Cómo hacerlo con two pointers?
Ahí es donde creces como desarrollador.
Consejo importante
NO midas tu progreso por cuántos problemas resuelves. Mídelo por:
- cuánto entiendes
- cuánto mejoras tu lógica
- cuánto dependes menos de Google
- cuánto mejor descompones problemas
Mi recomendación para practicar diariamente
Haz esto:
Rutina de 30 minutos
10 min
Leer y entender problema.
10 min
Resolver manualmente y pseudocódigo.
10 min
Implementar y refactorizar.
Haz eso todos los días durante meses. Tu cerebro cambia muchísimo.
Los mejores resolviendo algoritmos normalmente NO son los que más saben sintaxis, son los que mejor piensan.
Conclusión
Aprender algoritmos no se trata de memorizar soluciones complejas.
Se trata de:
- entender problemas
- dividirlos
- detectar patrones
- practicar consistentemente
Y sobre todo:
aprender a pensar paso a paso.
Porque al final, programar realmente es eso: resolver problemas.
BONUS
Vamos a solucionar una kata de esas que no son tan fáciles.
- Pronic Number
Task:
You have to create a function to check whether the argument passed is a Pronic Number and return true if it is & false otherwise.
Description:
Pronic Number -A pronic number, oblong number, rectangular number or heteromecic number, is a number which is the product of two consecutive integers, that is, n(n + 1).
The first few Pronic Numbers are - 0, 2, 6, 12, 20, 30, 42...
Explanation:
0 = 0 × 1 // ∴ 0 is a Pronic Number
2 = 1 × 2 // ∴ 2 is a Pronic Number
6 = 2 × 3 // ∴ 6 is a Pronic Number
12 = 3 × 4 // ∴ 12 is a Pronic Number
20 = 4 × 5 // ∴ 20 is a Pronic Number
30 = 5 × 6 // ∴ 30 is a Pronic Number
42 = 6 × 7 // ∴ 42 is a Pronic Number
Note:
Negative numbers are tested as well.
---
funcion que nos dan inicialmente:
function isPronic(n){
// Happy Coding ^_^
}
---
Test:
assert.strictEqual(isPronic(5),false,'5 is not a Pronic Number');
assert.strictEqual(isPronic(6),true,'6 is a Pronic Number');
assert.strictEqual(isPronic(-3),false,'-3 is not a Pronic Number');
assert.strictEqual(isPronic(-27),false,'-27 is not a Pronic Number');
y aqui esta la solucion:
El problema
Tenemos que crear una función que determine si un número es un Pronic Number. **Un número pronic es el resultado de multiplicar dos números consecutivos: ** n * (n + 1)
Ejemplos:
0 = 0 × 1
2 = 1 × 2
6 = 2 × 3
12 = 3 × 4
20 = 4 × 5
Entonces:
isPronic(6) // true
isPronic(5) // false
Lo primero que hago: NO programar
El error más común es abrir el editor e intentar escribir código inmediatamente. Primero quiero entender el patrón.
Analizando el patrón
Veo esta secuencia:
0
2
6
12
20
30
42
Y también veo esto:
0 = 0 × 1
2 = 1 × 2
6 = 2 × 3
12 = 3 × 4
Entonces mi cerebro comienza a pensar:
ok...
el número debe poder escribirse como:
x * (x + 1)
o sea:
dos números consecutivos multiplicados
Ahora pienso cómo comprobar eso
Aquí normalmente me hago preguntas.
- ¿Cómo descubro si un número cumple la regla?
- ¿Necesito matemática complicada?
- ¿O simplemente puedo probar números?
Y aquí aparece algo importante:
Muchas veces la solución más simple es suficiente.
Pensando como programador
Si recibo:
6
Yo podría probar:
0 × 1 = 0
1 × 2 = 2
2 × 3 = 6
Encontré coincidencia.
Entonces:
6 sí es pronic
Entonces ya tengo una estrategia
Mi lógica será:
empezar desde 0
multiplicar:
x * (x + 1)
si el resultado es igual al número:
retornar true
si me paso:
retornar false
Casos negativos
El problema dice algo importante:
Negative numbers are tested as well.
Y aquí mi cerebro piensa:
espera... ¿puedo multiplicar dos consecutivos y obtener negativo?
Ejemplos:
2 × 3 = 6
3 × 4 = 12
Siempre positivo o cero.
Entonces:
cualquier número negativo automáticamente es false
Eso simplifica muchísimo.
Pseudocódigo
Antes de JavaScript:
si el número es negativo
retornar false
empezar loop desde 0
mientras el resultado no supere n
calcular:
x * (x + 1)
si es igual a n
retornar true
retornar false
Ahora sí: JavaScript
function isPronic(n) {
if (n < 0) {
return false;
}
let current = 0;
while (current * (current + 1) <= n) {
if (current * (current + 1) === n) {
return true;
}
current++;
}
return false;
}
Explicando el código paso a paso
1. Validamos negativos
if (n < 0) {
return false;
}
No existen números pronic negativos.
2. Creamos un contador
let current = 0;
Este número representará:
x
en:
x * (x + 1)
3. Recorremos posibles combinaciones
while (current * (current + 1) <= n)
Aquí estoy diciendo:
mientras no me pase del número seguir intentando
4. Verificamos coincidencia
if (current * (current + 1) === n)
Si encontramos exactamente el número:
return true;
5. Probamos el siguiente consecutivo
current++;
Cómo pensé realmente este algoritmo Y esta es probablemente la parte más importante.
Mi razonamiento real fue algo así:
No necesito matemática avanzada.
Solo necesito detectar el patrón.
El patrón es:
x * (x + 1)
Entonces puedo probar valores.
Si encuentro coincidencia:
true.
Si me paso:
false.
Eso es resolver algoritmos. Es aprender a descomponer problemas.
Algo importante que debes entender
Muchos developers creen que resolver algoritmos significa encontrar soluciones súper complejas.
Pero en la vida real:
las mejores soluciones normalmente nacen de lógica simple bien pensada.
Resultado final
function isPronic(n) {
if (n < 0) {
return false;
}
let current = 0;
while (current * (current + 1) <= n) {
if (current * (current + 1) === n) {
return true;
}
current++;
}
return false;
}
