duduromeroa.com

Algoritmos en programación: parte 2

Fundamentos de algoritmos en programación con Javascript: Instancia del algoritmo, armando un algoritmo, pseudocódigo, ejemplos en Javascript


George Póyla, matemático. Resolver problemas de diseño. www.duduromeroa.com

Por Eduardo J. Romero Andrade
, Guayaquil, Ecuador

Contacto duduromeroa@gmail.com


#fundamentosProgramacion, #algoritmos, #javascript, #Guayaquil, #duduromeroa


Muchos de los conceptos relacionados a los fundamentos en algoritmos serán también explicados en código de programación. El lenguaje a usar será Javascript. Si deseas revisar a profundidad ese lenguaje, puedes ir a esta sección.



El problema a resolver: la instancia del algoritmo

Un concepto importante en el contexto de los algoritmos es el de instancia. Esto es, cuando cada conjunto de datos permite iniciar los cálculos que podrían dar respuestas a una duda o problema. En otras palabras, una instancia es el problema planteado desde la información conocida. Por ejemplo, si deseamos saber únicamente cuál es el valor final de la secuencia 5, 10, 15, 20, crearemos una instancia de problema (expondremos los datos conocidos) y luego se aplicará un sencillo algoritmo:

En Javascript

function secuencia(){
// Instancia : secuencia numérica a resolver
var nums = [5, 10, 15, 20];
// Toma la posición del último número -contando desde la pos. cero-
// Le suma 5
var numFinal = nums[3] + 5;
// Devuelve sumado 
return numFinal;
} 
console.log(secuencia());
//25

A pesar de que el resultado es correcto, no es un enfoque eficaz. Puesto que el algoritmo no es autónomo. Depende de la acción de un observador externo para agregar un valor que redondee la secuencia. Si el observador pausa esa acción o ingresa un dato incorrecto (una letra, por ejemplo; o ingresa el número 55 en vez de 5) entonces el algoritmo no funcionará o dará un resultado errado.

Un mejor enfoque permite que el algoritmo reciba una instancia y ejecute el cálculo sin dependencia de un tercero en su operación:

En Javascript

// Una función con una variable o parámetro
function secuencia(nums) {
     // nums[nums.length - 1]
     // Toma el último número y le suma 5
     var numFinal = nums[nums.length - 1] + 5; 
     // Devuelve esa suma
     return numFinal;
     // FIN de algoritmo
}

// Fuera de la función
// Se inserta cualquier secuencia desde incrementos de 5
var nums = [95, 100, 105];
// Se accede y se activa la función
console.log(secuencia(nums));
// 110

Otra vez, que un proceso obtenga un resultado correcto no siempre significará que sus acciones hayan sido las correctas. En el caso anterior, el algoritmo (expresado en un tipo de dato conocido como función) es endeble en su estructura, pues un simple error de ingreso daría un resultado erróneo. ¿Qué hará el algoritmo si la secuencia no es ingresada?, y ¿si la secuencia es incorrecta?, ¿o tiene solo un valor?, ¿o si ese valor no es un número?. Sin respuestas a preguntas clave, entonces no hay algoritmo (Horowitz, 1998, p. 9).

Más eventos deberán ser considerados (incluso los inesperados, tal cual ocurre en el mundo real) si deseamos que un algoritmo sea eficaz y completo. Abajo, una lista de eventos que los ejemplos anteriores deberían cubrir:

  1. Inicio del algoritmo
  2. Confirmar la presencia de una secuencia numérica con incrementos de 5 unidades
  3. Confirmar que la secuencia cumpla esa condición
  4. Alertar si no lo cumple
  5. Corregir la condición incumplida
  6. Se accede al último número
  7. Al último número se suman 5 unidades numéricas
  8. Confirmar que las unidades sean numéricas
  9. Alertar si no lo son
  10. Insertar unidades correctas
  11. Confirmar que la suma fue realizada
  12. Insertar ese número en la secuencia
  13. Confirmar que la secuencia es correcta
  14. Alertar si no lo es
  15. Corregir la condición incumplida
  16. Si el resultado da una secuencia correcta, finalizar
  17. Fin del algoritmo

En el siguiente ejemplo, un simple algoritmo ordenará (de menor a mayor) solo dos números cualesquiera mediante operadores lógicos y una condicional. En este caso, lo específico del pedido también es su debilidad, puesto que el algoritmo estará limitado a un solo contexto; es decir, al ordenamiento de únicamente dos números.

En Javascript

// Variables
var a = 88;
var b = 13;

// El primer número es menor o igual al segundo?
if (a <=b) {
// Sí es menor
    console.log(a + "," + b);
} else {
// No es menor, es mayor
    console.log(b + "," + a);
}
// 13,88

Un algoritmo más completo preverá el ordenamiento de más de dos números, como el de este ejemplo de Angelos Chalaris, tomado del sitio web 30secondsofcode.


Armando un algoritmo

Pensemos en un algoritmo como un equipo de fútbol, donde cada jugador representa una tarea por cumplir, de inicio a fin. Cada pase y toque de pelota debe ayudar a cada jugador hasta lograr meter la pelota en el arco contrario. Si el gol no ocurre, todo vuelve a reiniciarse, y el algoritmo volverá a ejecutar las acciones según los nuevos datos ingresados hasta finalmente lograr el resultado esperado.

El criterio de utilidad es clave. El método preciso de crear un algoritmo debe ser útil para algo: despejar una duda, facilitar un cálculo complejo con cientos de variables y constantes, o provocar una respuesta insospechada. En el siguiente breve ejercicio se demostrará cómo.

Definir una duda, planear un algoritmo, ejecutarlo

Un algoritmo debe ser útil para algo: despejar una duda, facilitar un cálculo complejo, provocar una respuesta precisa a una duda insólita.

¿Un algoritmo es similar a una expresión matemática?

Los algoritmos fueron, desde su origen, operaciones matemáticas para demostrar resultados. En el contexto moderno de cómputo, el aporte de un algoritmo es exponer la secuencia correcta de operaciones. El objetivo de un algoritmo hoy en día es doble: demostrar cómo llegar a un resultado, y que esos pasos puedan ser comprobados y validados desde cualquier lenguaje de programación.

Un sencillo ejemplo de eso sería la siguiente expresión textual: Pagué por dos encebollados a $3 cada uno. Pero la Juanita me regaló un jugo por cada plato, a $1.75 cada vaso. Entonces, ¿Cuánto debía pagar si Juanita no hubiera estado?

Con ese conjunto de proposiciones iniciaremos elaborando una secuencia de operaciones conocida como pseudocódigo. Luego, transformaremos el pseudocódigo en una sintaxis de lenguaje de programación para hacer los cálculos desde un computador. La sintaxis refiere al uso de signos de agrupación, de lectura y recuperación de datos, propios de cada código que un computador "leerá y entenderá".

Pseudocódigo

Una método para convertir una expresión textual a una secuencia que podamos transformar luego en código de programación es crear un pseudocódigo: este no es más que una lista de proposiciones con verbos que evocan la captura, alojamiento y recuperación de datos para luego, interpretarlo desde un lenguaje de programación.

Tomando el sencillo ejemplo de los encebollados, tendremos lo siguiente:


  1. Inicia pseudocódigo
  2. costoEncebollado 3
  3. costoJugo 1.75
  4. hubieraPagado (costoEncebollado x dos platos) + (costoJugo x 2 jugos)
  5. Comprobar:
  6. Si el costoEncebollado x dos platos es igual a restar el total a pagar sin el descuento:
  7. Es decir, si costoEncebollado * 2 == hubieraPagado - costoJugo * 2
  8. Entonces, la comprobación es correcta
  9. Sino, es errónea
  10. Fin


Tome en cuenta que fueron usados dos tipos de signos, uno para asignación y otro para igualdad.

Ahora, tomando en cuenta el pseudocódigo anterior intentaremos convertir esas asignaciones en una sintaxis de lenguaje de programación. En este y en el resto de ejemplos se usará el lenguaje de programación Javascript:

En Javascript

var costoEncebollado = 3;
var costoJugo = 1.75;
var hubieraPagado =  costoEncebollado * 2 + costoJugo * 2;

console.log("Compré dos encebollados a $" + costoEncebollado * 2);
console.log("Juanita me regaló dos jugos. Eso es $" + costoJugo * 2);
console.log("Si Juanita no hubiera estado, pagaría $" + hubieraPagado);

// Verificación
if (costoEncebollado * 2 === hubieraPagado - costoJugo * 2) {
    console.log("Comprobación correcta.");
} else {
    console.log("Error");
}

/*
Compré dos encebollados a $6
Juanita me regaló dos jugos. Eso es $3.5
Si Juanita no hubiera estado, pagaría $9.5
Comprobación correcta.
*/ 

La interpretación mediante código de programación significa usar la sintaxis para alojar datos en identificadores llamados variables. Eso es reconocible mediante la palabra var seguida por un nombre identificador, cuya asignación es el dato asignado. Luego, los signos (* para multiplicar, + para sumar, - para restar) operan los datos. Finalmente, una operación condicional if(){} evaluará la validez del algoritmo al comparar los datos operados de forma alterna.

Si desea profundizar en la sintaxis de Javascript, puede ir a esta sección para una revisión más amplia.



En otro ejemplo: 'Edú nació en el año 1976. La tecnología del año 2044 le permitió reducir 11.7 años de su edad biológica. Según eso, ¿cuántos años de edad tendría Edú en el 2044?' para generar un pseudo algoritmo que permita operar y comprobar que esa operación es correcta:


  1. Inicia pseudocódigo
  2. nacimiento = 1976
  3. futuro = 2044
  4. reduce = 11.7
  5. edadReal = futuro - el año de nacimiento
  6. edadFinal = edadReal - reduce (los años reducidos)
  7. Comprobar
  8. Si edadFinal + reduce == edadReal, entonces mostrar edadFinal
  9. Sino, mostrar error
  10. Fin


En Javascript

var nacimiento = 1976;
var futuro = 2044;
var reduce = 11.7;

// La edad de Edú en el año 2044 
var edadReal = futuro - nacimiento; 

// La edad de Edú en el año 2044 al reducirse 11.7 años
var edadFinal = edadReal - reduce; 

// Si (la edad de Edú en el 2044...
// ...más los años reducidos es igual a la edad que tendría en el 2044)..
if (edadFinal + reduce == edadReal) {
// Es igual
console.log("En el 2044 Edú tendrá " + edadFinal + 
" años de edad si se reduce 11.7 años");
} else {
// No es igual
console.log("Error");
}

// Resultado 
// En el 2044, tendrá 56.3 años de edad.

Nótese la sintaxis (signos, palabras clave, estructura) del lenguaje Javascript en este muy básico algoritmo. Incluso, en la forma de exponer los resultados mediante la oración "La edad de Edú en el 2044..."

Hasta aquí una breve explicación del aporte de los algoritmos en computación. Con una lista ordenada y lógica de acciones para obtener un resultado los algoritmos nos permiten aprovechar cualquier lenguaje de programación para insertar, alojar y recuperar datos; y cuyo correcto tratamiento matemático nos puede dar respuestas a problemas diversos.


BIBLIOGRAFÍA
Cormen, T., Leiserson, Ch., Rivest, R., Stein, C. (2022) Introduction to Algorithms (4ta. Ed.) MIT press.

Neapolitan, R. (2015) Foundations of Algorithms Jones, Bartlett Learning Press.

Horowitz, E., Sahni, S., Rajasekaran, S. (1999) Computer algorithms Computer Science Press, W. H. Freeman.

Knuth, Donald, E. (1997) The art of computer programming. 3ed. Vol. 1. Addison Wesley Longman ed.

Soto Apolinar, Efraín (2011) Diccionario ilustrado de conceptos matemáticos. 3ed edición. México.