Skip to content

1.2 Problemas, algoritmos y programas

Problemas

Podríamos decir que la programación es una forma de resolución de problemas.

Para que un problema pueda resolverse utilizando un programa informático, éste tiene que poder resolverse de forma mecánica; es decir, mediante una secuencia de instrucciones u operaciones que se puedan llevar a cabo de manera automática por un ordenador.

Ejemplos de problemas resolubles mediante un ordenador

  • Determinar el producto de dos números a y b.
  • Determinar la raíz cuadrada positiva del número 2.
  • Determinar la raíz cuadrada positiva de un número n cualquiera.
  • Determinar si el número n, entero mayor que uno, es primo.
  • Dada la lista de palabras, determinar las palabras repetidas.
  • Determinar si la palabra p es del idioma castellano.
  • Ordenar y listar alfabéticamente todas las palabras del castellano.
  • Dibujar en pantalla un círculo de radio r.
  • Separar las silabas de una palabra p.
  • A partir de la fotografía de un vehículo, reconocer y leer su matrícula.
  • Traducir un texto de castellano a inglés.
  • Detectar posibles tumores a partir de imágenes radiográficas.

Por otra parte, el científico Alan Turing, demostró que existen problemas irresolubles, de los que ningún ordenador será capaz de obtener nunca su solución.

Los problemas deben definirse de forma general y precisa, evitando ambigüedades.

Ejemplo: Raíz cuadrada

  • Determinar la raíz cuadrada de un número n.
  • Determinar la raíz cuadrada de un número n, entero no negativo, cualquiera.

Ejemplo: Dividir

  • Calcular la división de dos números de dos números a y b.
  • Calcular el cociente entero de la división a/b, donde a y b son números enteros y b es distinto de cero. (5/2 = 2).
  • Calcular el cociente real de la división a/b, donde a y b son números reales y b es distinto de cero (5/2 = 2.5).

Algoritmos

Dado un problema P, un algoritmo es un conjunto de reglas o pasos que indican cómo resolver P en un tiempo finito.

Secuencias de reglas básicas que utilizamos para realizar operaciones aritméticas: sumas, restas, productos y divisiones.

Ejemplo: Algoritmo para desayunar

Inicio
    Sentarse
    Servirse café con leche
    Servirse azucar
    Si tengo tiempo
        Mientras tenga apetito
            Untar mantequilla en una tostada
            Añadir mermelada
            Comer la tostada
        Fin Mientras
    Fin Si
    Beberse el café con leche
    Levantarse
Fin

Un algoritmo, por tanto, no es más que la secuencia de pasos que se deben seguir para solucionar un problema específico. La descripción o nivel de detalle de la solución de un problema en términos algorítmicos depende de qué o quién debe entenderlo, interpretarlo y resolverlo.

Los algoritmos son independientes de los lenguajes de programación y de las computadoras donde se ejecutan. Un mismo algoritmo puede ser expresado en diferentes lenguajes de programación y podría ser ejecutado en diferentes dispositivos. Piensa en una receta de cocina, ésta puede ser expresada en castellano, inglés o francés, podría ser cocinada en fogón o vitrocerámica, por un cocinero o más, etc. Pero independientemente de todas estas circunstancias, el plato se preparará siguiendo los mismos pasos.

Características de los algoritmos

Un algoritmo, para que sea válido, tiene que tener ciertas características fundamentales:

  • Generalidad: han de definirse de forma general, utilizando identificadores o parámetros. Un algoritmo debe resolver toda una clase de problemas y no un problema aislado particular.
  • Finitud: han de llevarse a cabo en un tiempo finito, es decir, el algoritmo ha de acabar necesariamente tras un número finito de pasos.
  • Definibilidad: han de estar definidos de forma exacta y precisa, sin ambigüedades.
  • Eficiencia: han de resolver el problema de forma rápida y eficiente.

Representación de algoritmos

organigrama

Los métodos más usuales para representar algoritmos son los diagramas de flujo y el pseudocódigo. Ambos son sistemas de representación independientes de cualquier lenguaje de programación. Hay que tener en cuenta que el diseño de un algoritmo constituye un paso previo a la codificación de un programa en un lenguaje de programación determinado (C, C++, Java, Pascal). La independencia del algoritmo del lenguaje de programación facilita, precisamente, la posterior codificación en el lenguaje elegido.

Diagrama de flujo (Flowchart) es una de las técnicas de representación de algoritmos más antiguas y más utilizadas, aunque su empleo disminuyó considerablemente con los lenguajes de programación estructurados. Un diagrama de flujo utiliza símbolos estándar que contienen los pasos del algoritmo escritos en esos símbolos, unidos por flechas denominadas líneas de flujo que indican la secuencia en que deben ejecutarse.

Los símbolos más utilizados son:

diagrama_flujo

Ejemplo: Mostrar dos números ordenados de menor a mayor

mostrarMenorMayor

Pseudocódigo es un lenguaje de descripción de algoritmos que está muy próximo a la sintaxis que utilizan los lenguajes de programación. Nace como medio para representar las estructuras de control de programación estructurada.

El pseudocódigo no se puede ejecutar nunca en el ordenador, sino que tiene que traducirse a un lenguaje de programación (codificación). La ventaja del pseudocódigo, frente a los diagramas de flujo, es que se puede modificar más fácilmente si detecta un error en la lógica del algoritmo, y puede ser traducido fácilmente a los lenguajes estructurados como Pascal, C, fortran, Java, etc.

El Pseudocódigo utiliza palabras reservadas (en sus orígenes se escribían en inglés) para representar las sucesivas acciones. Para mayor legibilidad utiliza la identación -sangría en el margen izquierdo- de sus líneas.

Ejemplo: Mostrar dos números ordenados de menor a mayor"*.

1
2
3
4
5
6
7
8
Inicio
    Leer (A, B)
    Si (A>B) Entonces
        Escribir (B, A)
    SiNo
        Escribir (A, B)
    FinSi
Fin

Ejemplo: Mostrar la potencia de un número elevado a otro número

1
2
3
4
5
6
7
8
Inicio
    Leer (A, B)
    RESULTADO<-1
    Desde contador<-1 hasta B con Paso 1 Hacer
        RESULTADO<-RESULTADO*B
    FinDesde
    Escribir (RESULTADO)
Fin

Programas

Algoritmo vs Programa

La diferencia fundamental entre algoritmo y programa es que, en el segundo, los pasos que permiten resolver el problema, deben escribirse en un determinado lenguaje de programación para que puedan ser ejecutados en el ordenador y así obtener la solución.

Los lenguajes de programación son sólo un medio para expresar el algoritmo y el ordenador un procesador para ejecutarlo. El diseño de los algoritmos será una tarea que necesitará de la creatividad y conocimientos de las técnicas de programación. Estilos distintos, de distintos programadores a la hora de obtener la solución del problema, darán lugar a programas diferentes, igualmente válidos.

Pero cuando los problemas son complejos, es necesario descomponer éstos en subproblemas más simples y, a su vez, en otros más pequeños. Estas estrategias reciben el nombre de diseño descendente (Metodología de diseño de programas, consistente en la descomposición del problema en problemas más sencillos de resolver) o diseño modular (top‐down design) (Metodología de diseño de programas, que consiste en dividir la solución a un problema en módulos más pequeños o subprogramas; las soluciones de los módulos se unirán para obtener la solución general del problema). Este sistema se basa en el lema divide y vencerás.

Estructura y Bloques Fundamentales de un programa

1
2
3
4
5
6
7
8
public class holaMundo {
    // programa Hola Mundo
    public static void main(String[] args) {
        /* lo único que hace este programa es mostrar
           la cadena "Hola Mundo!" por pantalla */
        System.out.println("Hola Mundo!");
    }
}

Desglosemos el ejemplo anterior:

En Java, generalmente, una clase lleva el identificador public y corresponde con un fichero. El nombre de la clase coincide con el del fichero .java respetando mayúsculas y minúsculas.

1
2
3
public class holaMundo {
    [...]
}

El código java en las clases se agrupa en funciones o métodos. Cuando java ejecuta el código de una clase busca la función o método main() para ejecutarla. Es público (public) estático (static) para llamarlo sin instanciar la clase. No devuelve ningún valor (void) y admite parámetros (Strings [] args) que en este caso no se han utilizado.

1
2
3
4
5
6
[...]
    public static void main (Strings [] args)
    {
        [...]
    }
[...]

El código de la función main se escribe entre las llaves. Por ejemplo:

1
2
3
[...]
        System.out.println("Hola Mundo");
[...]

Muestra por pantalla el mensaje Hola Mundo, ya que la clase System tiene un atributo out con dos métodos: print() y println(). La diferencia es que println muestra mensaje e introduce un retorno de carro.

Todas las instrucciones menos las llaves { } terminan con punto y coma ( ; ) .

Sangrado o Indentación

El sangrado (también conocido como indentación) deberá aplicarse a toda estructura que esté lógicamente contenida dentro de otra. El sangrado será de un tabulador. Es suficiente entre 2 y 4 espacios. Para alguien que empieza a programar suele ser preferible unos 4 espacios, ya que se ve todo más claro.

Las líneas no tendrán, en ningún caso, demasiados caracteres que impidan que se pueda leer en una pantalla. Un número máximo recomendable suele estar entre unos 70 y 90 caracteres, incluyendo los espacios de sangrado. Si una línea debe ocupar más caracteres, tiene que dividirse en dos o más líneas, para ello utiliza los siguientes principios para realizar la división:

  • Tras una coma.
  • Antes de un operador, que pasará a la línea siguiente.
  • Una construcción de alto nivel (por ejemplo, una expresión con paréntesis).
  • La nueva línea deberá alinearse con un sangrado lógico, respecto al punto de ruptura.

Unos ejemplos, para comprender mejor:

Dividir tras una coma:

1
2
3
funcion(expresionMuuuuyLarga1,
         expresionMuuuyyyyLarga2, 
         expresionMuuuyyyLarga3);

Mantener la expresión entre paréntesis en la misma línea:

1
2
3
nombreLargo = nombreLargo2*
              (nombreLargo3 + nombreLArgo4)+
              4*nombreLargo5;

Siempre hay excepciones. Puede resultar que al aplicar estas reglas, en operaciones muy largas, o expresiones lógicas enormes, el sangrado sea ilegible. En estos casos, el convenio se puede relajar.