Uno de los mayores retos para un programador es resolver problemas utilizando el algoritmo adecuado. Si importar la cantidad de lenguajes que el programador conozca, es muy importante saber resolver problemas l贸gicos de la forma correcta.
驴Cu谩les son los pasos para resolver un problema de programaci贸n?
Para esto vamos a seguir cinco pasos que nos ayudar谩n a acercarnos a la soluci贸n lo mas posible.
- Entender el problema.
- Explorar ejemplos concretos.
- Descomponer el problema.
- Solucionar/Simplificar.
- Retroceder y refactorizar.
I. Entender el problema
驴Cu谩les son las preguntas que debes realizar para resolver un problema de programaci贸n?
Imaginemos que estamos participando en una entrevista y el problema no es alguno que hayamos preparado durante nuestra fase de estudio de preparaci贸n. Antes de iniciar realiza las siguientes preguntas.
- 驴Puedo describir el problema con mis propias palabras?
- 驴Cu谩les son las entradas que involucra el problema?
- 驴Cu谩les son las salidas que retorna el problema?
- 驴Las salidas pueden ser determinadas a partir de las entradas? (Tenemos la suficiente informaci贸n para resolver el problema)
Ejemplo del planteamiento de un problema de programaci贸n
Por ejemplo, para el siguiente problema… “Escriba una funci贸n que tome dos n煤meros y retorne la suma de estos.”
1. Describir el problema con tus propias palabras.
Realizar una suma de dos n煤meros.
2. Cu谩les son las entradas que involucra el problema?
num1 y num2 (int, float?)
3. Cu谩les son las salidas que retorna el problema?
int, float, ?
4. Las salidas pueden ser determinadas a partir de las entradas?
II. Problemas en Concreto
Este es el segundo paso a realizar para entender el problema. El plantear problemas concretos ayuda entendiendo mejor el problema. Los ejemplos tambi茅n ayudan de forma que podemos validar que el la soluci贸n al problema funciona como se espera ya que en ese punto conocemos las entradas y salidas del programa.
Esto aplica en una escala mas grande como:
- Utilizando user stories.
- Unit tests (pruebas unitarias).
Al explorar ejemplos posibles…
- Inicia con ejemplos sencillos.
- Avanza a ejemplos mas complejos.
- Explora ejemplos con entradas vac铆as.
- Explora ejemplos con entradas inv谩lidas.
1. Inicia con ejemplos sencillos
Ejemplo… Crea una funci贸n que tome un string y retorne el n煤mero de caracteres dentro del string.
contarCaracteres("aaaa"); // { a: 4, b: c }
contarCaracteres("hola"); // { a: 1, o: 1, l: 1, a: 1 }
En este primer ejemplo preguntamos si debemos indicar para los caracteres que no existen el valor igual a 0, esto simplificar铆a el incrementar el valor cuando este aparezca en lugar de validar si esta presente o no.
2. Avanza a ejemplos mas complejos
Ahora supongamos que la entrada es mas larga.
contarCaracteres("mi direcci贸n es Calle siempre viva #");
驴Debemos contar espacios o si los valores acentuados como la 贸 son un valor mas al contar la o? 驴Qu茅 pasa con may煤sculas y min煤sculas?
3. Explora ejemplos con entradas vac铆as
Al momento de explorar las entradas vac铆as tenemos que preguntarnos que sucede con las salidas.
contarCaracteres(""); // {}
驴Para una entrada vac铆a, la salida deber铆a ser 0, null, un objeto vac铆o o una excepci贸n?
4. Explora ejemplos con entradas inv谩lidas
Plantea que es lo que sucede cuando el valor de entrada es no valido.
contarCaracteres(true); // ?
驴Si no es proporcionado un string se debe generar un error o una excepci贸n?
III. Descomponer el problema en partes
Antes de empezar a escribir c贸digo es recomendable descomponer el problema a resolver agregando comentarios acerca del enfoque que vamos a tomar para solucionar el problema.
Escribe los pasos que vas a tomar para solucionar el problema, solo incluyendo los componentes b谩sicos del problema. Esto te lleva a pensar en el c贸digo antes de empezar a escribirlo y detectar problemas o malentendidos antes de que te adentres y te tengas que preocupar acerca de detalles como el uso de la sintaxis.
function contarCaracteres(str) {
// convertir a minusculas
// construir objeto
// recorrer cada caracter del string
// si el caracter no es valido continuar con la siguiente iteracion
// si el caracter no existe en el objeto, crearlo
// incrementar
}
// retornar el objeto
}
Una de las ventajas de realizar este proceso durante una entrevista es que incluso si no logras completar la implementaci贸n, el enfoque provisto puede beneficiarte a la hora de ser evaluado, ya que describe la manera en que pretendes solucionar el problema.
IV. Solucionar el problema
Soluciona el problema, y si es posible soluciona el problema de forma sencilla. Es decir, trata de ignorar las partes complicadas, es decir, en lugar de gastar el tiempo en las partes complicadas enfocate en la parte que puedas solucionar. Cuando termines con este ataca aquella que consideres mas complicada.
- Encuentra la parte mas complicada.
- Ignora esta parte de forma temporal.
- Escribe una soluci贸n simplificada.
- Despu茅s incorpora la parte completa.
function contarCaracteres(str) {
// convertir a minusculas
str = str.toLowerCase();
// construir objeto
let salida = {};
// recorrer cada caracter del string
for (let i = 0; i < str.length; i++) {
const char = str[i];
// si el caracter no es valido continuar con la siguiente iteracion
if (char.match(/[^a-z0-9]/)) {
continue;
}
// si el caracter no existe en el objeto, crearlo
if (salida[char] === undefined) {
salida[char] = 0;
}
// incrementar
salida[char]++;
}
// retornar el objeto
return salida;
}
console.log(contarCaracteres("Hola Mundo"));
Salida.
{ H: 1, o: 2, l: 1, a: 1, M: 1, u: 1, n: 1, d: 1 }
V. Retroceder / Refactorizar
Al refactorizar el c贸digo aseg煤rate de realizar las siguientes preguntas.
- 驴Es posible revisar el resultado?
- 驴Es posible obtener el resultado de una forma diferente?
- 驴Es posible entender el algoritmo con una mirada?
- 驴Es posible reutilizar el m茅todo para otro problema?
- 驴Es posible mejorar el performance de la soluci贸n propuesta?
- 驴Existen otras formas de refactorizar?
- 驴Este problema ha sido solucionado por otras personas?
En el caso del algoritmo propuesto tiene mucho valor el hacer menci贸n a una posible ineficiencia o demanda adicional de recursos cuando se utilizan expresiones regulares en lenguajes como JavaScript.