Revistas en Papel
Anterior
Menú
Logotipo

AMIGA.InFo • Mayo/Junio 1995 • Número 3

Parte 3: VARIABLES EN LOS ALGORITMOS

INICIACIÓN A LA PROGRAMACION
 

IMPLEMENTACIÓN DE LOS
ALGORITMOS EN EL AMIGA

Una vez aprendido el método que se debe seguir para diseñar alhoritmos, estamos en condiciones para avanzar, un poco más, en el aprendizaje de la programación. El siguiente paso a seguir es el de diseñar nuevos algoritmos utilizando datos que se puedan contabilizar en el ordenador. En vez de hablar de bombillas, café, sal o aceite, utilizaremos el concepto de variable: números enteros o reales, letras, etc... Al trabajar con variables, nos encontraremos con toda una serie de nuevos conceptos que, al principio, nos sorprenderán un poco pero que muy pronto empezaréis a dominar.

A.Moreno

NOTA: Pulsando sobre las fotos con borde azul ampliarás la imagen.

Antes de empezar a hablar de variables, quiero solucionar uno de los algoritmos que planteamos el número pasado. Se trata del ejercicio número 3 que decía lo siguiente:

3. Desarrollar un algoritmo para hacer una llamada telefónica.

No sé por qué motivo, pero este simple enunciado ha sido el que más problemas ha planteado. En general, la mayoría de lectores que nos han mandado los ejercicios resueltos hacía bastante bien el resto de los ejercicios y sin embargo, cuando llegaban al tercero, se quedaban sin ideas. Por si os sirve de algo, puedo deciros que, cuando programo, intento ponerme en el lugar de la máquina y entonces pienso en cómo solucionaría yo el problema.

Para entender mejor el método, vamos a intentar diseñar un algoritmo para solucionar el problema de la llamada telefónica. Tomaremos como guía el algoritmo que nos ha mandado JAVIER SAEZ de Santa Coloma de Gramanet (Barcelona). Esto no significa que su diseño no sea el más adecuado, simplemente he escogido su diseño como recompensa al duro trabajo que ha hecho solucionando todos los ejercicios. ¡Bravo! sigue así y muy pronto serás todo un "genio" de la programación.

Algoritmo LLAMADA TELEFÓNICA

  1. Descolgar el auricular.
  2. Esperar a oír la señal de línea libre = pitido agudo.
  3. Cuando haya línea libre, pulsar sobre los números elegidos.

Realizado por Javier Saez.

En primer lugar, hay que tener muy en cuenta que tenemos que realizar el análisis descendente. Es decir, diseñaremos el algoritmo haciendo sucesivas aproximaciones de forma que cada una de ellas sea más detallada que la anterior. Uno de los "errores" que se suele cometer al principio es el de diseñar el algoritmo de golpe, en una sola pasada. Por ejemplo, me habéis mandado la solución final de cada ejercicio. De esta forma no sé si habéis diseñado el algoritmo de una vez o habéis aplicado el análisis descendente. Es bastante aconsejable que guardéis las diferentes aproximaciones junto a la documentación de vuestro programa ya que, algún día, os puede ser de gran ayuda. Así que, empezaremos diseñando una primera aproximación:

En primer lugar, nos tenemos que preguntar qué cosas necesitamos para poder solucionar el problema. En nuestro caso, nos bastará con conocer el número de teléfono que queremos marcar, un teléfono, línea telefónica, una mano, una oreja...

Cuando ya tenemos claro qué datos iniciales necesitamos y qué resultados deseamos, entonces ya podemos ponernos a diseñar el algoritmo. Por ejemplo, veamos la primera aproximación:

1ª APROXIMACIÓN
  1. Conseguir el número a marcar.
  2. Localizar un teléfono.
  3. Descolgar el auricular.
  4. Esperar hasta oír la señal de línea libre (pitido agudo).
  5. Marcar el número de teléfono (en este momento ya hay línea libre).
  6. Esperar (hasta oír contestación o hasta que nos cansemos de esperar).

Mientras hemos diseñado estos primeros seis pasos, seguro que se nos han ido ocurriendo nuevas aproximaciones, más pasos, hemos visto que nos hace falta un nuevo dato inicial, etc... Poco a poco iremos depurando el diseño. Tras pensar un buen rato ya testaremos en condiciones de abordar una segunda aproximación:

Conseguir el número a marcar quedará de la siguiente forma:

  1. SI (no sé de memoria el número a marcar)
       Buscarlo en la agenda.
     SINO
       Recordarlo
     FinDelSI.

Localizar un teléfono quedará de la siguiente forma:

  2. SI (Me acuerdo en la Calle)
       Buscar la cabina telefónica más cercana
     SINO
       Llamar desde mi casa
     FinDelSI.

Y así seguiríamos detallando, aún más, cada uno de los pasos. Por ejemplo el punto uno, podría quedar así, más o menos, en una tercera aproximación:

  1. SI (No sé de memoria el número a marcar)
     AGENDA()
     SINO
       Recordarlo
     FinDelSI.

Donde la función AGENDA() sería de la siguiente forma:

  1.1 Coger la Agenda.
  1.2 Abrir la Agenda.
  1.3 REPETIR HASTA (que se encuentre el nombre a buscar)
      Si (se ha acabado la página
        Pasar a la siguiente página.
      SINO
        Leer teléfono.
      FinDelSI.
      FinDelREPETIR.
  1.4 Apuntar el nombre, dirección y número de teléfono.
  1.5 Cerrar la Agenda.
  1.6 Dejar la Agenda.

Como podéis ver, el método que hay que seguir para desarrollar un algoritmo es muy sencillo. Ahora, veamos cómo se puede desarrollar un algoritmo que lo solucione un ordenador.


Trabajando con ordenadores

La forma de trabajar de los ordenadores es muy peculiar. Se puede decir que utilizando únicamente números y letras consiguen solucionar la mayoría de los problemas informáticos. Tal y como vimos en el artículo del número 1 de Amiga.InFo, la memoria del ordenador está compuesta por toda una serie de posiciones en las cuales podemos guardar todo tipo de información. Por ejemplo, podemos almacenar instrucciones, números, nombres, listados, dibujos, etc... Cada una de estas posiciones de memoria recibe el nombre de "byte" y está representada por una única dirección asociada. Por supuesto, su contenido puede cambiar a lo largo de la ejecución de nuestro programa.


¿Cómo podemos usar nosotros la memoria del ordenador?

Pues bien, cada vez que necesitamos guardar cualquier información, tendremos que reservar un espacio de memoria y darle un nombre. Por ejemplo, si necesitamos guardar el año actual podemos utilizar una pequeña zona de memoria donde guardar el número 1995. Veamos cómo haríamos esta reserva de memoria:

Algoritmo AñoPróximo
Variables: AñoActual del tipo número,
           AñoPróximo del tipo número;
AñoActual:= 1995;
AñoPróximo:= 0;
AñoPróximo:= AñoActual+1;
Mostrar por pantalla AñoPróximo;
FinAlgoritmo.

Este simple algoritmo utiliza únicamente dos zonas de la memoria donde almacenar información. Estas dos zonas de memoria reciben el nombre de variables. En este caso, hemos indicado que son del tipo número. Es decir, contienen un dato numérico. En general, las variables pueden contener datos de diferente índole: naturales, enteros, reales, caracteres, booleanos, etc.. Y te preguntarás.. ¿Qué son booleanos? Muy fácil, los booleanos son un tipo de variables que sólo puede contener dos valores posibles. Por ejemplo: cierto o falso, uno o cero, si o no, etc...

Una vez que se han declarado las variables que utilizaremos en nuestro programa, ya podemos inicializarlas. La línea

  AñoActual:= 1995;

Le dice al ordenador que la dirección de memoria asociada a AñoActual toma por valor la cantidad 1995. Este tipo de instrucción recibe el nombre de asignación. es decir, a la variable llamada AñoActual se le asigna el valor 1995. Análogamente, asignamos cero a la posición de memoria designada por AñoPróximo. Una vez que las variables están declaradas e inicializadas, ya podemos hacer operaciones con ellas. Por ejemplo, le sumamos una undiad para que tengan en valor 1996 y lo guardamos en la variable AñoPróximo.

Ahora, vamos a solucionar uno de los problemas iniciales de todo curso de programación. Se trata de diseñar un algoritmo para intercambiar el valor de dos variables. Por ejemplo, tendremos dos variables llamadas X e Y cuyos valores finales estarán intercambiados.

Cuando uno se encuentra con este problema, la primera reacción más evidente es la siguiente: Utilizo una variable extra que me sirve de apoyo para el intercambio y problema resuelto. Veamos este posible diseño:

Algoritmo Intercambio
Variables: X del tipo natural,
           Y del tipo natural.,
           Auxiliar del tipo natural;
           Auxiliar:=Y;
           Y:=X;
           X:=Auxiliar;
FinAlgoritmo.
Implementación en Modula-2 del Algoritmo Intercambio1
MODULE Intercambio1;
(* Este programa intercambia el valor de dos variables y
lo muestra por pantalla *)
FROM InOut IMPORT ReadInt, WriteInt, WriteString, WriteLn;
VAR
  X,Y: INTEGER;
BEGIN
  (* Lee los valores iniciales de X e Y*)
  WriteString("Escribe el valor inicial para la X: ");
  WriteLn;
  ReadInt(X);
  WriteLn;
  WriteString("Escribe el valor inicial para la Y: ");
  WriteLn;
  ReadInt(Y);
  (* Hace el intercambio de valores *)
  X:=X-Y;
  Y:=Y+X;
  X:=Y-X;
  (* Muestra los valores actuales de X e Y *)
  WriteString("El valor actual de X es: ");
  WriteLn;
  WriteInt(X,3);
  WriteLn;
  WriteString("El valor actual de Y es: ");
  WriteLn;
  WriteInt(Y,3);
  WriteLn;
  END Intercambio1.

Implementación en C del Algoritmo Intercambio1
/* Este programa intercambia el valor de dos variables y
lo muestra por pantalla */
#include <stdio.h>
main()
{
   int X,Y;
   /* Lee los valores iniciales de X e Y */
   printf("Escribe el valor inicial para la X: \n");
   scanf("%d",&X;);
   printf("Escribe el valor inicial para la Y: \n");
   scanf("%d",&Y;);
   /* Hace el intercambio de valores */
   X=X-Y;
   Y=Y+X;
   X=Y-X;
   /* Muestra los valores actuales de X e Y */
   printf("El valor actual de X es: \n %d \n", X);
   printf("El valor actual de Y es: \n %d \n", Y);
}

Como podéis observar, esta solución es muy clara, pero estamos gastanto una posición de memoria que, en algunos casos, puede llegar a ser muy necesaria para otras cosas. Vamos a intentar diseñar otra posible solución, pero ahora, sin utilizar ninguna variable adicional. El "truquillo" de este segundo algoritmo cuesta un poco de ver pero, si te paras a pensar un poco, lo verás enseguida. Nos aprovecharemos de las propiedades de la suma y de la resta para conseguir solucionar el problema.

Algoritmo Intercambio1
Variables: X del tipo natural,
           Y del tipo natural;
           X:=X-Y;
           Y:=Y+X;
           X:=Y-X;
FinAlgoritmo.

Este algoritmo ya no es tan claro pero resuelve el problema inicial de intercambiar el valor de dos variables. En este caso nos ahorramos memoria pero ,a cambio, perdemos velocidad ya que hay que realizar una serie de operaciones matemáticas para conseguir el resultado final. Siempre nos encontaremos con una de estas dos dualidades. Unas veces necesitaremos que el programa sea veloz, y otras veces necesitaremos que el programa no consuma demasiada memoria, recursos del sistema, etc... será decisión del programador optar por una solución u otra. Además, hay que tener en cuentra que se pueden diseñar multitud de algoritmos, todos correctos, y que solucionen el problema de forma adecuada. Por lo tanto, siempre se ha de escoger el algoritmo más simple y que solucione el problema inicial en menos pasos sin sacrificar a cambio la legibilidad del programa.

Por ejemplo, veamos un tercer algoritmo, también correcto, para solucionar el problema del intercambio de los valores de las variables.

Algoritmo Intercambio2
Variables: X del tipo natural,
           Y del tipo natural;
       X:=X+Y;
       Y:=X-Y;
       X:=X-Y;
FinAlgoritmo.

Y se podrían diseñar por lo menos 100 versiones diferentes más, utilizando multiplicaciones, o divisiones, o cualquier otra idea feliz que se nos ocurra. Debido a esto, siempre tenéis que recordar que hay que quedarse con el algoritmo más simple ya que será más fácil de mantener y, por supuesto, la posibilidad de que tenga errores es mucho menor que un algoritmo mucho más complicado.


Y cuando tenemos el Algoritmo ¿Qué?

Una vez diseñado el algoritmo podemos pasar a codificarlo en cualquiera de los lenguaje de programación existentes para Amiga. Por ejemplo, vamos a implementar el algoritmo Intercambio1 en Modula-2 y en C. ¿Cómo? Sí, sí. Una vez que hemos diseñado un algoritmo, luego podemos implementarlo en el lenguaje de programación que más nos guste o que mejor se adapte a las características del algoritmo. Por ejemplo, si el algoritmo utiliza gran cantidad de punteros, entonces es mejor utilizar el C que, por ejemplo, el PASCAL. Esta es una de las ventajas que tiene la algorítmica, ya que resulta muy fácil de codificar en cualquier lenguaje, ya sea de alto o bajo nivel.

Otro dato importante que nunca debéis de olvidar es que, no es una buena costumbre diseñar un programa directamente en el lenguaje de programación que más dominemos. Si diseñamos el algoritmo directamente en un lenguaje de programación, podemos adquirir pequeños vicios propios de ese lenguaje que nos pueden dar problemas a la hora de compartir nuestro código con otros programadores o, también, al intentar pasar código fuente a otro nuevo lenguaje de programación.

Por último y antes de pasar a otro ejemplo, quiero mencionaros otro de los problemas que suelen presentarse cuando nos ponemos a programar. Se trata de hacer pequeñas "chapuzas" o trucos para conseguir más velocidad de ejecución. Hay que ir con mucho ojo cuando hagamos esas pequeñas "chapuzas", o de lo contrario nos pasará como a la mayoría de demos y viejos juegos, que presentan un algo grado de incompatibilidad entre diferentes modelos de Amiga.

A muy pequeña escala, vamos a ver uno de estos trucos para conseguir más velocidad en la implementación en C del Algoritmo Intercambio1. La pérdida de tiempo se produce al efectuar los cálculos para hacer el intercambio de los valores de las variables, por tanto es ahí donde aplicaremos el truco.

Como podéis ver en el código en C, situado bajo este párrafo, la idea es muy simple ¿verdad?. Se trata de mostrar el valor de la variable Y cuando toca mostrar el de la variable X y viceversa. En este caso "da el pego", pero el algoritmo está totalmente mal diseñado, aunque al ejecutarlo de el resultado esperado.

#include <stdio.h>
main()
{
   int X,Y;
   /* Lee los valores iniciales */
   printf("Escribe el valor inicial para la X: \n");
   scanf("%d",%X);
   printf("Escribe el valor inicial para  la Y: \n");
   scanf("%d",&Y;);
   printf("El valor actual de X es: \n %d \n", Y);
   printf("El valor actual de Y es: \n %d \n";
}


Un Último ejemplo

Para intentar dejar claras las ideas vistas en el artículo de este mes, vamos a ver un último ejemplo que servirá como resumen. En primer lugar, siempre se necesita un enunciado lo más claro posible y, sobre todo, libre de ambigüedades. En este caso el enunciado será el siguiente:

- Dada una cadena de caracteres introducidos mediante el teclado y acabada en un "." contar el número de veces que aparece el carácter "A".

Nota: La cadena de caracteres estará compuesta únicamente por letras en mayúsculas.

Ejemplo: Dada la cadena "EN UN LUGAR DE LA MANCHA DE CUYO NOMBRE NO QUIERO ACORDARME.", el programa ha de indicar que el carácter A ha aparecido 6 veces.

El siguiente paso a dar es el de pensar un poco antes de empezar a diseñar el algoritmo. Cuando ya tenemos las ideas claras, entonces cogemos papel y lápiz y pasamos a diseñarlo.

La mejor forma de abordar su resolución es pensar cómo resolveríamos nosotros este problema si nos encontrásemos en lugar del ordenador. Por ejemplo, en primer lugar deberíamos informar de qué sabemos hacer. Normalmente, este paso suele ser siempre igual. Consiste en indicarle al usuario cuales son los pasos que ha de seguir para que nos pueda ejecutar correctamente. Es decir, mostraremos las instrucciones de uso del programa. En este momento, el usuario ya sabe qué tiene que hacer, así que, ya podemos empezar en serio.

Sabemos, gracias al enunciado, que nos va a introducir una cadena de caracteres tan grande como quiera pero que, siempre estará acabada por un punto. Por lo tanto nuestra tarea va a consistir en procesar la cadena de caracteres hasta que nos llegue el punto que indicará el fin. Este dato es muy importante, ya que es el que marcará el cuerpo principal del programa.

Ahora ya sabemos hasta cuando tenemos que procesar caracteres. Pero, ¿en qué consiste exactamente la tarea de procesar los caracteres introducidos por el teclado?. Bien, el enunciado dice que tenemos que contar cuantas veces aparece la vocal A mayúscula, por lo tanto, seguiremos el mismo proceso que seguiríamos nosotros si nos preguntasen cuántas A's hay en una frase. Es decir:

Iremos leyendo letras hasta que nos llegue el punto final. Si la letra que hemos leído era una A, entonces sumaremos uno al contador de A's aparecidas. Por supuesto, el contador ha de empezar desde cero.

Algoritmo Para Contar AS
Algoritmo ContarAS
Variables: Letra del tipo Carácter,
           Contador del tipo Entero;
           MostrarPorPantallaLasInstrucciones()
           Leer(Letra);
           Contador := 0;
           MIENTRAS Letra NoEsIgual ":" HACER
                 SI Letra = "A" ENTONCES
                          Contador := Contador+1;
                 FinDelSI.
                 Leer(Letra);
          FinDelMientras.
          MostrarPorPantallaElContador()
FinAlgoritmo.

Arriba podéis encontrar el algoritmo ya finalizado. Una vez que lo tenemos diseñado, el siguiente paso a dar es el de escoger en qué lenguaje de programación lo vamos a implementar. Por ejemplo, abajo puedes ver como quedaría la implementación en Módula-2, pero se puede implementar perfectamente en cualquier lenguaje: C, Pascal, Ensamblador, ADA, E, etc...


Ejercicio

Para que podáis practicar en casa, os voy a proponer un enunciado que espero que os haga pensar un poco:

  • Dada una cadena de caracteres introducidos mediante el teclado y acabada en un ".", contar el número de veces que parece la combinación "LA".

Nota: La cadena de caracteres estará compuesta únicamente por letras en mayúsculas.

Ejemplo Dada la cadena "EN ALABAMA MOLA LA BALA.", el programa ha de indicar que la combinación LA ha aparecido 4 veces.

Para solucionarlo, tenéis que seguir el proceso que hemos visto en el Algoritmo de contar A's. Una vez que lo tengáis diseñado, mandádmelo para que podamos discutir posibles fallos.

Si conocéis algún lenguaje de programación, sería muy interesante que implementárais el Algoritmo de contar LA's y lo compilárais. De esta forma se pueden ver los errores al mismo tiempo que se aprende a programar todavía más. En el próximo artículo seguiremos profundizando en el arte de la programación.

Implementación en Modula-2 del Algoritmo ContarAS
(*Este programa se encarga de, dada una cadena de caracteres
introducidos mediante el teclado y acabada en un ".", contar
el número de veces que encuentra el carácter "A" *)
MODULE CuentaA;
FROM InOut IMPORT Read,WriteInt,Write,WriteString, WriteLn;
VAR
  LetraLedia: CHAR; Contador: INTEGER;
BEGIN
  WriteLn;
  WriteString("Introduce una secuencia de caracteres en mayúsculas ");
  WriteString("y acabada en .");
  WriteLn;
  Read (LetraLeida);
  Contador := 0;
  WHILE LetraLeida <> "." DO
        IF LetraLeida = "A" THEN Contador := Contador+1
        END;
        Read (LetraLeida);
  END;
  WriteLn;
  WriteString ("El carácter A ha aparecido:    ");
  WriteInt (Contador,10);
  WriteString (" veces. ");
  WriteLn;
END CuentaA.

Envía esta página web a un amigo:
Esta opción está desactivada temporalmente, rogamos disculpen las molestias

Volver a la página anterior

Al menú principal