Skip to content

Unidad 1: Resolución de problemas

Resolución de problemas Proceso de resolución de problemas Algoritmo Programa Refinamiento progresivo Representación de los algoritmos

En esta primera unidad abordaremos el proceso de Resolución de Problemas desde el punto de vista de la informática e iremos asimilando algunos conceptos básicos que nos permitirán comprender el Desarrollo de Aplicaciones. Pero antes de empezar, ¿qué es la informática? Podemos entenderla como la ciencia que estudia el tratamiento automático y racional de la información. El término informática nace en la década de 1960 en Francia, bajo la denominación INFORMATIQUE, que surge de la contracción de las palabras INFORmation y autoMATIQUE. Es, en definitiva, el tratamiento automático de la información.

El proceso de resolución de un problema con una computadora conduce al desarrollo de un programa (o software en inglés) y a la ejecución del mismo. Un programa contiene un conjunto de instrucciones y algoritmos que le indican a la computadora cómo resolver el problema. Pero, antes de diseñar un algoritmo, debemos haber analizado y comprendido el problema lo suficiente como para plantear una solución. Para ello, existen una serie de fases que generalmente deben seguir todos los programadores para llegar a una solución efectiva.

Proceso de resolución de problemas

Nosotros nos enfocaremos en informatizar el proceso de resolución de problemas del mundo real. Por ejemplo, podríamos querer resolver ecuaciones complejas que nos permitan planificar y llevar a cabo un determinado proyecto, ¡como lanzar un cohete a la luna!, o calcular las ganancias obtenidas en un determinado período en una empresa, u otras más sencillas, como obtener la lista de empleados que cumplan años en un determinado día para felicitarlos y organizar un almuerzo.

Estableceremos cinco fases que deben llevarse a cabo para resolver un problema, de manera iterativa:

Análisis del problema Diseño del algoritmo Codificación Verificación Mantenimiento

El proceso comienza analizando y entendiendo en profundidad el problema. Este paso es fundamental, aunque pueda parecer banal, ya que la solución brindada responderá al problema que nosotros hemos entendido que debe resolverse (que podrá diferir de lo que otras personas entiendan y/o de lo que realmente se pretendía). Esta fase define lo que el programa debe hacer, pero no cómo lo debe hacer.

Una vez analizado y comprendido el problema, se diseña una solución que conducirá al algoritmo que resuelva el problema. Es decir, se define cómo lo debe hacer el programa.

Posteriormente este algoritmo será codificado en un lenguaje de programación para que pueda ser ejecutado por una computadora. En esta fase escribimos el programa.

La fase de verificación empezará junto con la fase de diseño del algoritmo, y continuará a lo largo del desarrollo del sistema. Una vez que el programa esté codificado, se diseñarán pruebas que deben asegurarse de verificar la mayor cantidad de posibles caminos que el programa puede tomar, para así encontrar errores (o bugs en inglés) aún no descubiertos y corregirlos. Esta fase se enfoca en verificar que el programa hace lo que debe hacer.

En la fase de mantenimiento el programa se actualiza y modifica según sea necesario para ajustarse a los cambios de necesidades de los usurarios. Además, seguramente surgirán errores que serán detectados por los usuarios y que no hayan sido descubiertos durante la fase de verificación. También podríamos querer añadir características y funcionalidades extras y, debido al constante cambio de hardware, probablemente debamos actualizarlos para adaptarlo a los nuevos dispositivos.

Finalmente, se debe documentar principalmente las fases de análisis, diseño y codificación, como así también generar manuales de usuario y establecer normas para el mantenimiento.

Análisis del problema

La primera fase consiste en comprender y analizar el problema para definir lo que debe hacer el programa. Dicho programa será ejecutado en una computadora, por lo tanto, es importante entender el modelo computacional. De esta manera, podemos resumir el análisis a la respuesta de las siguientes preguntas:

  • ¿Qué datos de entrada se requiere?
  • ¿Qué resultados de salida se espera?
  • ¿Qué proceso conduce a la salida esperada?
  • Requerimientos adicionales y restricciones.

El modelo computacional

Para resolver un problema utilizando una computadora debemos entender que la lógica de éstas consiste básicamente en leer un dato, procesarlo, y devolver un resultado. Por lo tanto, se puede pensar en un modelo computacional compuesto de tres partes: entrada, proceso y salida:

Entrada Proceso Salida

Ejemplo 1.1: Entrada, Proceso y Salida de un problema sencillo

Supongamos que somos la persona encargada de entregar los paquetes en una empresa de Correo y queremos diseñar un algoritmo que indique como llevar a cabo nuestro trabajo para, eventualmente, desarrollar un software que pueda ser ejecutado por un robot y realice este trabajo por nosotros. Lo primero que debemos hacer es preguntarnos ¿qué necesito para empezar el proceso?, la respuesta a esta pregunta se conoce como datos de entrada. En este ejemplo, se necesita el código de envío para poder iniciar el proceso.

A continuación, describiremos a grandes rasgos los pasos necesarios para llevar a cabo el proceso:

  1. Solicitarle al cliente el código de envío.
  2. Verificar que el paquete se encuentre listo para ser entregado.
  3. Buscar el paquete.
  4. Entregar el paquete.

La salida o resultado de este proceso consiste en la entrega del paquete al cliente que lo solicita.

Algoritmo

Un algoritmo es un método formal y sistemático de representar la descripción de un proceso. Dichos algoritmos son independientes tanto del modo en que se representan como de la persona/objeto/computadora que los ejecuta. Podemos hacer una analogía con una receta de cocina, por ejemplo, que se puede expresar en distintos idiomas: español, inglés, francés, etc. pero de ninguna manera esto influye en los pasos que distintos cocineros (que hablen distintos idiomas) deben seguir para ejecutar la receta.

El término algoritmo surge del nombre del matemático persa Al-Khôwarizmi, quien vivió alrededor del año 825 después de Cristo. Al-Khôwarizmi escribió tratados de Aritmética y Algebra y se hizo especialmente popular al enunciar las reglas paso a paso para sumar, restar, multiplicar y dividir números decimales. La traducción al latín de su apellido es algorismus, que posteriormente derivó en algoritmo. Al-Khôwarizmi, junto con Euclides (siglo IV a.C.), quien inventó un método para encontrar el máximo común divisor de dos números, son considerados los padres de la algoritmia, ciencia que estudia los algoritmos.

No existe un único algoritmo para resolver un determinado problema. Distintas personas diseñarán distintos algoritmos y todos serán igualmente válidos. Escribir algoritmos es un arte, en el que cada persona le da su toque personal, aunque todos deben cumplir las siguientes características:

  • Un algoritmo debe ser preciso: debe indicar de manera clara y sin ambigüedades cada uno de los pasos a seguir para conseguir el objetivo propuesto.
  • Un algoritmo debe ser exacto: si ejecutáramos dicho algoritmo varias veces con el mismo conjunto de datos de entrada, los resultados obtenidos deben ser los mismos.
  • Un algoritmo debe ser finito: debe poder ejecutarse en un tiempo finito.

Diseño de algoritmos

En la ciencia de la computación y en la programación, los algoritmos son más importantes que los lenguajes de programación o las computadoras, ya que estos dos últimos son sólo un medio para expresar y ejecutar el algoritmo. Por lo tanto, es muy importante llevar a cabo un buen diseño de algoritmo, que requiere de creatividad y un conocimiento profundo en las áreas involucradas, aunque usualmente se puede facilitar esta tarea dividiendo el problema en pequeños sub-problemas, que probablemente requerirán un proceso más simple para ser resueltos. Este método se conoce como “divide y vencerás” o refinamiento progresivo.

Refinamiento progresivo

Al diseñar un algoritmo normalmente se inicia diseñando un primer esbozo a partir del modelado que se realizó cuando se analizó el problema, que tiene un nivel de abstracción alto, e indicará en unos pocos pasos (y probablemente de manera incompleta) como resolver el problema. A continuación, se realizan otras iteraciones que irán descomponiendo el problema y diseñando algoritmos más detallados y específicos. Este proceso se denomina diseño descendente o refinamiento progresivo.

Por ejemplo, en una primera iteración del algoritmo del Ejemplo 1.1 podríamos obtener la siguiente secuencia de pasos, un poco más detallada:

nix
1. Solicitarle al cliente el código de envío.
2. Verificar que la persona que retira el paquete está autorizada a hacerlo.
    2.1. Si no está autorizada, rechazar la solicitud del cliente y terminar el proceso.
3. Verificar que el paquete se encuentre listo para ser entregado.
    3.1. Si el paquete aún no está listo, informárselo al cliente y terminar el proceso.
4. Buscar el paquete.
5. Efectuar el cobro del servicio, si corresponde.
6. Hacerle firmar la constancia de entrega al cliente.
7. Entregar el paquete.
8. Terminar proceso.

Sucesivas iteraciones podrán detallar con mayor precisión los pasos para ejecutar con éxito el proceso, contemplando todas las situaciones y las reglas de negocio. Debemos tener en cuenta que quien ejecute nuestro algoritmo (probablemente una computadora) no tiene capacidad de razonamiento, a diferencia de los seres humanos. Por lo tanto, se debe especificar al máximo los pasos a seguir, ya que, si se presentara una situación desconocida, la computadora simplemente no sabrá que hacer y probablemente no obtengamos el resultado esperado.

Una vez que hayamos diseñado el algoritmo, será necesario representarlo de manera universal para que pueda ser transmitido a cualquier persona a fin a las ciencias de la computación.

Representación de los algoritmos

Existen diferentes métodos o lenguajes para representar los algoritmos, cada uno con su propia sintaxis, que es el conjunto de dibujos y/o palabras que se permite utilizar, y una semántica asociada, la cual se refiere al concepto que representa cada dibujo y/o palabra. Estos métodos se pueden clasificar gráficos (mediante dibujos) y no gráficos (mediante texto). Los más comunes son:

  • Representación gráfica
    • Diagrama de flujo
    • Diagrama de Nassi Schneiderman
  • Representación no gráfica
    • Lenguaje natural (el que hablamos las personas)
    • Fórmulas
    • Pseudocódigo
    • Lenguaje de programación
Representación de los algoritmos Representación Gráfica Representación No Gráfica Diagrama de Flujo Diagrama de Nassi Schneidermann Lenguaje de Programación (EsJS / JavaScript) Pseudocódigo Lenguaje Natural Fórmulas

Diagrama de flujo

Un diagrama de flujo (o flowchart en inglés) emplea símbolos que han sido normalizados por el Instituto Nacional de Normalización (ANSI). Los pasos del algoritmo son representados por estos símbolos, unidos por flechas llamadas líneas de flujo, que indican la secuencia en que se deben ejecutar. A continuación se muestran los símbolos más utilizados y la función de cada uno:

SímboloNombreFunción
Terminal
TerminalRepresenta el inicio y fin de un programa. También puede representar una interrupción programada que sea necesario realizar en un programa.
/Entrada/Salida/
Entrada/SalidaRepresenta cualquier tipo de introducción de datos en la memoria de un programa a partir de un dispositivo de entrada (teclado, disco, ratón), o la escritura de un dato en un dispositivo de salida (pantalla, disco, impresora).
Proceso
ProcesoCualquier operación que pueda modificar datos en memoria, operaciones aritméticas, etc.
Decision
DecisiónRepresenta la operación lógica o de compracación entre datos, y, según el resultado, determina el camino a tomar. Normalmente tiene dos caminos (SI o NO), pero puede tener más de dos si es necesario.
A--
Indicador de direcciónRepresenta el flujo de ejecución de las operaciones.
A---B
Línea conectoraRepresenta la unión entre dos símbolos.

Ejemplo 1.2: Diagrama de flujo de la suma de dos números

A continuación se ejemplifica el diagrama de flujo de un algoritmo que, como entrada recibe dos números A y B, calcula la suma de estos dos números, almacena el resultado en una variable C y luego muestra en pantalla el valor de la variable C.

Inicio /Leer A/ /Leer B/ C = A + B /Escribir C/ Fin inicio-- A-- B-- C-- D--

Diagrama de Nassi-Schneiderman (N-S)

El diagrama N-S es similar al diagrama de flujo, sólo que se omiten las flechas que indican el flujo y, en cambio, se utilizan bloques de cajas contiguas. Cada paso se escribe en cajas sucesivas.

Ejemplo 1.3: Diagrama de N-S de la suma de dos números

Siguiendo el Ejemplo 1.2, a continuación se muestra el diagrama de N-S para dicho algoritmo:

inicio
leer
A
leer
B
calcular
C = A + B
escribir
C
fin

Lectura complementaria: Representación de los algoritmos

Para profundizar acerca de las distintas formas de representación, se recomienda dirigirse al libro “Programación en Pascal (4° ed.)”, páginas 65-75.

Pseudocódigo

El pseudocódigo (falso lenguaje) es una herramienta de programación en la que las instrucciones se escriben en palabras similares al español o inglés y permite describir el funcionamiento de un algoritmo. Es una forma no gráfica de representar un algoritmo, aunque no tiene un conjunto de reglas definidas, sino que cada autor emplea las que cree conveniente. Para ello, define un conjunto de palabras reservadas. Una palabra reservada es una palabra que tiene un significado especial para el lenguaje de programación (en este caso, pseudocódigo), y no puede ser utilizado como identificador de variables, constantes u otros objetos. Por ejemplo, podemos utilizar las especificaciones UPSAM, que es un Pseudocódigo que define palabras reservadas en español, y un conjunto de reglas para utilizarlas. Allí se indica que un algoritmo debe empezar con la palabra reservada inicio y terminará con fin. Además, utilizaremos el concepto de identación, que es establecer una sangría o margen izquierdo en ciertas líneas. Generalmente se insertan 4 espacios o 1 tabulador para lograr la sangría izquierda. De manera que un algoritmo representado en pseudocódigo se verá como se muestra a continuación:

Untitled

El pseudocódigo utiliza expresiones matemáticas, expresiones lógicas, y la noción de variable, de la cual hablaremos en profundidad más delante, pero por ahora basta con saber que es un espacio de memoria que contiene un valor que puede ser modificado. Si necesitamos que el usuario introduzca un nuevo valor a una variable del algoritmo, utilizaremos la palabra reservada leer, seguida del nombre de la variable. Si el algoritmo necesita mostrar un valor, utilizaremos la palabra reservada escribir, seguida del nombre de la variable o expresión que se desea mostrar.

Ejemplo 1.4: Pseudocódigo de la suma de dos números

A continuación, se representa en pseudocódigo el algoritmo del Ejemplo 1.2:

nix
algoritmo suma_dos_numeros
var
    entero A
    entero B
    entero C
inicio
    leer(A)
    leer(B)
    C A + B
    escribir(C)
fin

Programa

La definición más básica es: un conjunto explícito de pasos a seguir para lograr un fin determinado.

Es decir, es un conjunto de instrucciones que, una vez ejecutados, realiza una o varias tareas en una computadora, otorgándonos la resolución del problema para el cual el programa fue diseñado. Los programas son una pieza fundamental de las computadoras. Sin programas, las computadoras no servirían para nada.

La codificación es la escritura en un lenguaje de programación de la representación del algoritmo que se ha generado en la segunda etapa del proceso de resolución de problemas. Para realizar la conversión del algoritmo en programa, se deben sustituir las instrucciones que hemos empleado en nuestro algoritmo, por las instrucciones equivalentes del lenguaje de programación que hayamos elegido.

Ejemplo 1.5: Código EsJS para la suma de dos números

En este ejemplo codificaremos el algoritmo del Ejemplo 1.2 utilizando el lenguaje de programación EsJS, que es el lenguaje que utilizaremos en éste módulo, y cuenta con una sintaxis en Español:

Desarrollo de Aplicaciones