unidad iv: lenguaje de diseño de algoritmos

UNIDAD IV: LENGUAJE DE DISEÑO DE ALGORITMOS ESTRUCTURAS DE CONTROL
ASIGNATURA: INTRODUCCIÓN A LA COMPUTACIÓN
CARRERAS: LICENCIATURA Y PROFESORADO
EN CIENCIAS DE LA COMPUTACIÓN
DEPARTAMENTO DE INFORMÁTICA
FACULTAD DE CIENCIAS FÍSICO MATEMÁTICA Y NATURALES
UNSL
1
4.1. Definición de variables
El Lenguaje de Diseño de Algoritmos (LDA) cuenta con dos tipos de objetos: constantes y variables.
En el caso de las variables debemos tener en cuenta que las mismas tienen como atributos, un
nombre que las identifica y el tipo que indica un conjunto de posibles valores que puede almacenar.
De lo anterior, surge la siguiente pregunta:
¿Cómo sabe el procesador cuáles son y de qué tipo son las variables que el algoritmo utilizará
para resolver el problema?
Es decir, se necesita especificar, por cada variable, el respectivo nombre y tipo. El tipo es necesario
para poder reservar un lugar de memoria (una casilla) que contenga adecuadamente los posibles
valores. El nombre es necesario para que puedan ser referenciadas (encontradas) cuando se las
necesite (por ejemplo, en una asignación) en cualquier acción primitiva en la que pueda aparecer una
variable.
En respuesta a la pregunta anterior, el LDA provee una regla de escritura para indicarle al procesador
nombre y tipo de las variables que se usarán en el algoritmo.
Proceso <nombre>
Definir <var1>, <var2>, ... ,<varN> Como (Real|Entero|Logico|Caracter);
------FinProceso
Se puede observar que se comienza el algoritmo con la palabra Proceso seguido del nombre del
algoritmo <nombre>. En la línea siguiente se comienzan a definir las variables que se utilizarán a lo
largo del algoritmo. Se utiliza la palabra reservada Definir seguido del nombre o nombres (separados
por comas) de las variables de uno de los siguientes tipos (Real|Entero|Logico|Caracter) que se
encuentra a la derecha de la palabra Como. Se finaliza cada definición con el símbolo ;. Si se desean
definir variables de varios tipos, se utilizarán varias líneas de la forma “Definir <var1>, <var2>, ...
,<varN> Como (Real|Entero|Logico|Carácter);”, al menos, una línea por cada tipo de variable
definida.
Veamos algunos ejemplos.
Ejemplo 1:
Proceso Primera_definición
Definir edad Como Entero;
Definir altura, peso Como Real;
Definir sexo Como Caracter;
edad <- 25;
altura <- 1.68;
sexo <- “F”;
FinProceso
En el Ejemplo 1, se puede ver la regla utilizada para definir variables: después de la palabra
reservada Definir va el nombre de la variable y después de la palabra reservada Como se coloca el
tipo. Se definieron una variable de tipo entero (edad), dos variables de tipo real (altura y peso) y una
variable de tipo caracter (sexo). Estas variables forman el ambiente del algoritmo, el cual se expresa
de la siguiente manera:
2
Objeto
Tipo
Descripción
edad
Variable de tipo entero.
Contiene una edad.
altura
Variable de tipo real.
Contiene una altura.
peso
Variable de tipo real.
Contiene un peso.
sexo
Variable de tipo caracter.
Contiene un sexo.
Si se utilizaran constantes significativas se deben agregar al ambiente.
Los identificadores, o nombres de variables, deben constar sólo de letras y números, comenzando
siempre con una letra y no pueden ser palabras reservadas.
Más abajo, en el algoritmo del ejemplo, después de las declaraciones, sólo se realizan tres
asignaciones, una a cada variable declarada. Si bien el algoritmo no resuelve ningún problema
específico, nos permite visualizar cómo se realizan las declaraciones.
Supongamos ahora que el algoritmo del Ejemplo 1 es cambiado por:
Ejemplo 2:
Proceso Segunda_definición
Definir altura, peso Como Real;
Definir sexo Como Caracter;
edad <- 25;
altura <- 1.68;
sexo <- “F”;
FinProceso
¿Qué problemas podemos detectar aquí? En otras palabras, ¿será capaz el procesador de entender y
ejecutar este algoritmo?
Claramente, la respuesta es NO porque la variable edad es desconocida para el procesador y por lo
tanto, no tiene casilla asignada en el ambiente para almacenar un valor de ningún tipo.
Consideremos ahora un ejemplo un tanto más práctico, en el sentido que pretendemos que el
procesador realice una tarea que resuelva un problema particular. Supongamos que se quiere diseñar
un algoritmo para calcular las raíces de una ecuación cuadrática donde los coeficientes de dicha
ecuación son a=2.0; b=3.0; y c=1.0. Recordemos que la fórmula para calcular dichas raíces es:
− b ± b 2 − 4ac
2a
El algoritmo para calcular las dos raíces, dados los valores de a, b y c, se da a continuación:
Ejemplo 3:
Proceso Raíces
Definir a, b, c Como Real;
Definir res1, res2 Como Real;
a <- 2.0;
3
b <- 3.0;
c <- 1.0;
res1 <- ( -1 * b + RC(b^2 - 4*a*c))/(2*a);
res2 <- ( -1 * b - RC(b^2 – 4*a*c))/(2* a);
FinProceso
Antes de analizar el algoritmo Raíces en detalle es importante observar que las variables a, b y c
fueron declaradas en una sola línea, lo único que se necesitó fue un separador (la coma “,”) para
poder diferenciar un nombre de otro. De igual manera se hizo con las variables res1 y res2 ya que
son del mismo tipo.
Ahora, el algoritmo Raíces parece calcular como corresponde las dos raíces de la ecuación dados los
valores de a, b y c. Sin embargo, ¿nos servirá de algo el algoritmo tal cual está diseñado? La
respuesta es NO y la razón es la siguiente: el algoritmo procesa un conjunto de datos, pero el
resultado o resultados que el usuario espera recibir no son comunicados de ninguna manera. Esto es,
el algoritmo no da un respuesta explícita para que el usuario pueda visualizar el resultado (en este
caso, el usuario necesitaría saber cuáles son los valores de las variables res1 y res2). En síntesis, el
problema detectado aquí es que no existen, hasta el momento, acciones que permitan realizar una
interacción del usuario con el algoritmo al momento de la ejecución. Por interacción, queremos
significar la posibilidad de ingresar datos a pedido (ENTRADA) o visualizar datos resultantes de los
cálculos (SALIDA). Éstas, son dos acciones básicas de gran importancia para la comunicación de
datos y serán explicadas en la siguiente sección.
4.2. Entrada-Salida de datos
4.2.1. Entrada de datos
Un valor que no pertenece al ambiente del algoritmo puede introducirse al mismo, mediante una
acción, que llamaremos lectura.
Lectura, es toda acción que permite la entrada de uno o más valores al ambiente del algoritmo a
través de un dispositivo. Una lectura es una asignación, en el sentido que toma valores del medio
externo y lo asigna a las variables del ambiente. La lectura es una acción primitiva.
En el LDA la lectura se nota de la siguiente manera:
Leer <variable1>, <variable2>, ...,<variableN>;
Esta acción lee N valores desde el mundo exterior, por ejemplo, desde el teclado y los asigna a las N
variables mencionadas, en el orden en que aparecen en la primitiva.
4.2.2. Salida de datos
Un valor puede comunicarse al mundo exterior, por ejemplo, a través de un dispositivo de salida.
Llamaremos escritura a la acción primitiva que permite la salida de valores a través de un
dispositivo. Esta acción toma uno o más valores y lo comunica al medio externo.
En el LDA la notaremos de la siguiente manera:
Escribir <expr1>, <expr2>, ..., <exprN>;
Además permite mostrar carteles informativos al usuario (encerrados entre comillas dobles) los
cuales pueden intercalarse con las expresiones (separados por comas). Por ejemplo:
4
Escribir “cartel informativo”, <expr1>;
Esta acción primitiva transmite valores del ambiente del algoritmo al mundo externo al mismo, por
ejemplo a la pantalla, es decir, muestra los valores obtenidos de evaluar las N expresiones. Dado que
puede incluir una o más expresiones, puede mostrar uno o más valores.
A los efectos de aumentar la legibilidad de un algoritmo antes del uso de una primitiva de lectura
suele usarse una de escritura en la cual se aclara lo que está esperando el algoritmo que ingrese el
usuario.
Ejemplo: si un algoritmo espera que un usuario ingrese un número entero, esto se expresa:
Escribir “Ingrese un número entero”;
Leer Num;
El mensaje que aparece en la pantalla es: Ingrese un número entero y el procesador queda esperando
que por el teclado se entre un número entero el cual se almacenará en la variable Num.
Análogamente cuando el algoritmo va a mostrar algún resultado, por ejemplo la cantidad promedio
de milímetros de agua de lluvias caída en un determinado mes, el diseñador del algoritmo escribirá:
Escribir “El promedio de milímetros de agua de lluvias del mes de Enero fue: ”, prom;
Suponiendo que la variable prom tiene almacenado el valor 150, el resultado de la ejecución de esta
acción primitiva mostrará en la pantalla:
El promedio de milímetros de lluvias del mes de Enero fue: 150
Es importante destacar que, en el ambiente, cuando resulte conveniente, pueden nombrarse también
los Datos Auxiliares. Aunque no son los requeridos por el problema, sirven como etapa intermedia
entre los Datos de Entrada y los Resultados o Datos de Salida.
Ejemplo 4:
Proceso Raíces
Definir a, b, c como Real;
Definir res1, res2 como Real;
Escribir “Ingrese coeficiente (a)”;
Leer a;
Escribir “Ingrese coeficiente (b)”;
Leer b;
Escribir “Ingrese coeficiente (c)”;
Leer c;
res1 <- ( -1 * b + RC( b ^ 2 – 4 *a *c )) / (2 * a);
res2 <- ( -1 * b - RC( b ^ 2 – 4 * a * c)) / (2 * a);
Escribir “Las raíces calculadas son: ”, res1, res2;
FinProceso
Con esta nueva versión del algoritmo Raíces podemos, por un lado, resolver una cuestión muy
importante: visualizar el resultado incluyendo un mensaje “Las raíces calculadas son:” para una
mejor comprensión de la SALIDA del algoritmo. Por otro lado, a través de la acción primitiva de
ENTRADA, hemos incluido en el algoritmo la posibilidad de que realicen los cálculos de las raíces
para más de un conjunto de datos. Recordemos que en el Ejemplo 3, el cálculo se hacía para a=2.0,
5
b=3.0 y c=1.0. En esta versión lo podemos hacer para los números anteriores y para cualquier otro
conjunto de números ingresados por el usuario al momento de ejecutarse las acciones Leer.
4.3 Estructuras de control
Estructurar el control de un conjunto de acciones detalladas en un algoritmo es brindar mecanismos
que permitan indicar el orden en que las mismas van a ser llevadas a cabo.
Una de las mayores potencias de un procesador proviene de su capacidad de tomar decisiones y de
determinar qué acción realizar al momento de ejecutar un algoritmo sobre la base de los valores de
algunos de los datos que se leen, o bien, de los resultados de los cálculos que se realizan.
Vamos a explicar tres conceptos muy importantes relacionados con estructuras de control:
• Secuencial
• Condicional
• Repetición
Estas acciones no modifican el ambiente sino el orden en que el procesador ejecuta las acciones
primitivas.
4.3.1 Estructura de Control Secuencial
Cuando no se indique lo contrario, el flujo de control de ejecución de un algoritmo seguirá la
secuencia implícita del mismo. Entendemos por secuencia implícita que las acciones se ejecutan en
el orden en que son escritas en el algoritmo, es decir, desde la primera hacia la última ("desde arriba
hacia abajo y de izquierda a derecha"). Al terminar de ejecutarse una acción se pasa a la inmediata
siguiente que está perfectamente determinada y, así siguiendo, hasta alcanzar la última acción del
algoritmo. Por ejemplo, las siguientes acciones primitivas representan una secuencia:
I <- 1;
Leer numero;
f <- numero + I;
Lo mismo podría visualizarse gráficamente a través de lo que se conoce como un Diagrama de
Flujo1 que sirve para visualizar todos los posibles órdenes de ejecución de un algoritmo. En él las
acciones primitivas que modifican el ambiente se escriben dentro de rectángulos. El ejemplo anterior
quedaría expresado con el siguiente diagrama:
I <- 1;
Leer numero;
f <- numero + I;
1
Los diagramas de flujo son una herramienta que permite representar visualmente qué operaciones se requieren y en qué secuencia se
deben efectuar para solucionar un problema dado. Es la representación gráfica, mediante símbolos especiales, de los pasos o
procedimientos de manera secuencial y lógica que se deben realizar para solucionar un problema dado. Facilitan la comprensión de
problemas complicados y sobre todo aquellos en que sus procesos son muy largos.
6
4.3.2 Estructura de Control Condicional
Un algoritmo permite resolver problemas de una misma clase. Sin embargo, en la mayoría de las
clases de problemas, no es posible hallar un conjunto de acciones secuenciales que permitan resolver
el problema. Recordemos que algunas acciones pueden tener que llevarse a cabo sólo para algunas
instancias o, lo que es lo mismo, sólo si ciertas condiciones se satisfacen. Cuanto más general intente
ser nuestro algoritmo es posible que deba considerar más alternativas.
Los algoritmos, en determinados momentos, requieren ser selectivos en lo que respecta a las acciones
que deben seguir, basándose en una respuesta de un determinado cuestionamiento que se formuló
para la solución del problema planteado.
En esta asignatura veremos dos tipos de estructura de control condicional: Condicional Simple y
Condicional Múltiple.
4.3.2.1 Condicional Simple
Nuestro LDA debe proveer algún mecanismo para expresar que un conjunto de acciones debe
ejecutarse sólo bajo ciertas condiciones. El condicional permitirá que una o un conjunto de acciones
primitivas se ejecuten sólo si cierta condición se cumple.
Por ejemplo:
Si n > 0 entonces decrementar n en 1
quiere decir que sólo restaremos 1 a n si n es un número positivo (n > 0). Las condiciones prevén las
distintas situaciones que pueden presentarse en la resolución del problema. El condicional permite
que la ejecución de cierto conjunto de acciones quede sometida a una condición.
Supongamos que X e Y son dos variables enteras, cada una un valor entero previamente asignado. El
problema planteado es mostrar por pantalla el mayor valor. Esto es, si X > Y debe escribirse el valor
de X; en caso contrario, el valor de Y. En este caso, es evidente que existen secuencias de acciones
alternativas: “escribir el valor de X” o “escribir el valor de Y”. La elección acerca de cuál de los dos
valores escribir depende de si el valor de X es o no mayor que el valor de Y.
El diagrama de flujo asociado con esta acción condicional es:
F
X>Y
Escribir Y;
V
Escribir X;
donde X > Y es una condición que se debe evaluar.
El resultado de esta acción completa es que el mayor de los dos valores de las variables X o Y, es el
que se escribirá. Por ejemplo, supongamos que X tiene el valor 8 e Y el valor 3. Como 8 es mayor que
3, la condición X > Y es Verdadera y, por lo tanto se escribirá el valor 8 como resultado de la acción
primitiva Escribir X;.
7
En este ejemplo sencillo hemos analizado la estructura de control condicional.
El formato algorítmico de dicha estructura y su correspondiente diagrama de flujo es:
Si <condición> Entonces
F
<alternativa verdadera>;
<condición>
V
Sino
<alternativa falsa>;
<alternativa verdadera>;
<alternativa falsa>;
FinSi
El inicio de la estructura comienza con la palabra reservada Si y el final con la palabra reservada
FinSi.
Ahora podemos reescribir el ejemplo anterior de la siguiente manera:
Si X > Y Entonces
Escribir X;
Sino
Escribir Y;
FinSi
Tanto la condición como cada una de las alternativas de la estructura pueden ser más complejas, por
ejemplo, la alternativa verdadera y la alternativa falsa pueden consistir de una secuencia de acciones
primitivas en lugar de una única acción (como en el ejemplo dado). La condición, a su vez, puede
consistir de una condición compuesta.
La estructura condicional se considera como un ente completo, es decir, al que se ingresa en el punto
en el cual la condición se evalúa. Una vez evaluada la condición se toma por una de las alternativas
y, luego, el control pasa a la acción primitiva que sigue al delimitador FinSi (si dicha acción existe).
Otro ejemplo:
Enunciado: Calcular la raíz cuadrada de un número, si éste no es negativo; en caso contrario no
realizar cálculo alguno.
Ambiente del algoritmo:
Objeto
a
Tipo
Descripción
Variable de entrada-salida de Como variable de entrada contendrá
tipo entero.
el número del cual se quiere calcular
la raíz cuadrada; como variable de
salida, contendrá la raíz cuadrada.
Algoritmo:
Versión 1:
t1. Definir las variables a ser utilizadas por el algoritmo.
8
t2. Leer el número del cual se desea calcular la raíz cuadrada, guardándolo en la variable a.
t3. Si su valor es positivo o cero entonces
t3.1. Calcular la raíz cuadrada usando la función primitiva RC( )
t3.2. Guardar el valor de la raíz en la variable a
t3.3. Escribir en pantalla el valor de la raíz
sino
hacer nada.
Versión 2: (final)
Proceso raíz_cuadrada
// t1.
Definir a Como Entero;
// t2.
Escribir “Ingrese el valor”;
Leer a;
// t3.
Si a >= 0 Entonces
// t3.1. y t3.2.
a <- RC(a);
// t3.3.
Escribir “La raíz cuadrada es: ”, a;
FinSi
FinProceso
En el algoritmo anterior las frases u oraciones escritas después de // representan comentarios y sirven
para documentar un algoritmo. Además el algoritmo anterior es, a la vez, un ejemplo donde un dato
de entrada puede también ser utilizado como dato de salida.
Puede suceder que, si la condición es falsa, no existan acciones a ejecutar (como en el ejemplo
anterior). En estos casos, en la construcción algorítmica no aparece el delimitador Sino y el formato
de la construcción condicional y su correspondiente diagrama de flujo es:
Si <condición> Entonces
<alternativa verdadera>;
F
<condición>
V
FinSi
<alternativa verdadera>;
9
Anidamiento de estructuras de control condicional
Hasta ahora, los algoritmos vistos sólo presentan una decisión para realizar un determinado proceso;
sin embargo, en algunas ocasiones es necesario elaborar estructuras condicionales en cascada o
anidadas. Esto significa que después de haber realizado una comparación selectiva es necesario
realizar otra comparación selectiva como resultado de la primera condición.
Analicemos el siguiente esquema, donde: p y q son condiciones y a, b, c y d, son acciones.
Si p Entonces
a;
Sino
b;
Si q Entonces
c;
Sino
d;
FinSi
FinSi
Veamos el resultado de todas las posibles ejecuciones de este algoritmo:
Predicados
Acciones a
p
q
Ejecutar
VERDADERO
VERDADERO
a
VERDADERO
FALSO
a
FALSO
VERDADERO
b, c
FALSO
FALSO
b, d
Estas instrucciones se pueden visualizar gráficamente a través de un diagrama de flujo:
F
p
a
b
F
d
q
V
V
c
10
A continuación se ejemplifica el uso de la estructura de control condicional anidada.
Enunciado: Los operarios de una empresa trabajan en tres turnos: uno matutino, cuyo código es 1,
otro vespertino cuyo código es 2 y el otro nocturno cuyo código es 3. Se desea calcular el jornal para
un operario sabiendo que, para el turno nocturno, el pago es de $5 la hora y para el turno vespertino
es de $3 la hora y para el matutino es de $2 la hora. En este último caso, si el día es domingo se paga
un adicional de $1 por hora.
Primero deberíamos analizar las diferentes fórmulas para calcular el jornal:
• Fórmula 1 (para el turno nocturno): jornal = 5 * horas trabajadas
• Fórmula 2 (para el turno vespertino): jornal = 3 * horas trabajadas
• Fórmula 3a (turno diurno, no es domingo): jornal = 2 * horas trabajadas
• Fórmula 3b (turno diurno, domingo): jornal = (2 + 1) * horas trabajadas.
Ambiente del algoritmo:
Objeto
Tipo
Descripción
horas
Variable de entrada,
numérico (entero).
de
tipo Almacena la cantidad de horas
trabajadas en un día, por un operario.
turno
Variable de entrada,
numérico (entero).
de
tipo Almacena el código del turno.
Variable
caracter.
entrada,
de
tipo Almacena si el día es domingo. Si su
valor es “d”, indica que es día
domingo, sino tiene el valor “n”
Variable de salida,
numérico (entero).
de
tipo Almacena el valor de la paga que debe
efectuarse por jornal.
dia
jornal
de
Algoritmo:
Versión 1:
t1. Definir las variables a ser utilizadas por el algoritmo.
t2. Leer datos de entrada.
t3. Calcular el jornal.
t4. Informar resultados.
Como las acciones de este algoritmo no son primitivas, aplicaremos la técnica de Refinamientos
Sucesivos.
Versión 2:
t1. Definir las variables a ser utilizadas por el algoritmo.
t2.1. Leer las horas trabajadas.
t2.2. Leer el código del turno.
t2.3. Leer el código del día.
t3. Si el turno es nocturno entonces
11
t3.1. Calcular el jornal usando la fórmula 1
sino
si el turno es vespertino entonces
t3.2. Calcular el jornal usando la fórmula 2
sino
t3.3. Calcular el jornal usando la fórmula 3
finsi
finsi
t4. Escribir el valor del jornal
Como la acción calcular el jornal usando la fórmula 3 no refleja todavía las restricciones del
problema debemos realizar un nuevo refinamiento:
Versión 3:
t1. Definir las variables a ser utilizadas por el algoritmo.
t2.1. Leer las horas trabajadas.
t2.2. Leer el código del turno.
t2.3. Leer el código del día.
t3. Si el turno es nocturno entonces
t3.1. Calcular el jornal usando la fórmula 1
sino
si el turno es vespertino entonces
t3.2. Calcular el jornal usando la fórmula 2
sino
si el día no es domingo entonces
t3.3.1. Calcular el jornal usando la fórmula 3a
sino
t3.3.2. Calcular el jornal usando la fórmula 3b
finsi
finsi
finsi
t4. Escribir el valor del jornal
Versión 4 (final):
Proceso Jornales
//t1.
Definir horas, turno, jornal Como Entero;
12
Definir dia Como Caracter;
//t2.1.
Escribir “Ingrese las horas trabajadas: ”;
Leer horas;
//t2.2.
Escribir “Ingrese el código del turno: ”;
Leer turno;
//t2.3.
Escribir “Ingrese el código del día: ”;
Leer dia;
Si turno = 3 Entonces
//t3.1.
jornal <- 5 * horas ;
Sino
Si turno = 2 Entonces
//t3.2.
jornal <- 3 * horas;
Sino
Si dia <> “d” Entonces
//t3.3.1.
jornal <- 2 * horas;
Sino
//t3.3.2.
jornal <- (2 + 1) * horas;
Finsi
FinSi
FinSi
//t4.
Escribir “El jornal del operario es: “, jornal;
FinProceso
Para ejecutar un algoritmo vamos a utilizar una tabla de ejecución. Dicha tabla contendrá tantas
columnas como variables se hayan definido, más una columna que se utiliza para mostrar lo que
aparecerá en la pantalla. Al definir las variables, el valor inicial que poseen las variables es
indeterminado y se representa con el siguiente símbolo “⊥”.
Supongamos que queremos ejecutar cuatro veces el algoritmo Jornales con los siguientes datos de
entrada (estos valores se almacenarán en las variables al ejecutarse las instrucciones de lectura):
Ejecución 1
Ejecución 2
Ejecución 3
Ejecución 4
horas: 8
horas: 12
horas: 10
horas: 7
turno: 1
turno: 2
turno: 3
turno: 1
dia: “n”
dia: “n”
dia: “n”
dia: “d”
13
Sólo en los ejemplos presentados en esta unidad se mostrará en la primera columna qué
instrucción se va ejecutando en cada paso de la ejecución.
Ejecución 1:
Instrucción
Definir horas, turno, jornal Como Entero;
horas
turno
⊥
⊥
dia
jornal
Pantalla
⊥
⊥
Definir dia Como Caracter;
Ingrese las horas trabajadas: 8
Escribir “Ingrese las horas trabajadas: ”;
8
Leer horas;
Ingrese el código del turno: 1
Escribir “Ingrese el código del turno: ”;
1
Leer turno;
Ingrese el código del día: n
Escribir “Ingrese el código del día: ”;
“n”
Leer dia;
¿turno = 3? -> NO
¿turno = 2? -> NO
¿dia <> “d”? -> SI
16
jornal <- 2 * horas;
El jornal del operario es: 16
Escribir “El jornal del operario es: “, jornal;
Ejecución 2:
Instrucción
Definir horas, turno, jornal Como Entero;
horas
turno
⊥
⊥
dia
jornal
Pantalla
⊥
⊥
Definir dia Como Caracter;
Ingrese las horas trabajadas: 12
Escribir “Ingrese las horas trabajadas: ”;
12
Leer horas;
Ingrese el código del turno: 2
Escribir “Ingrese el código del turno: ”;
2
Leer turno;
Ingrese el código del día: n
Escribir “Ingrese el código del día: ”;
“n”
Leer dia;
¿turno = 3? -> NO
¿turno = 2? -> SI
36
jornal <- 3 * horas;
El jornal del operario es: 36
Escribir “El jornal del operario es: “, jornal;
Ejecución 3:
Instrucción
Definir horas, turno, jornal Como Entero;
horas
turno
⊥
⊥
jornal
Pantalla
⊥
⊥
Definir dia Como Caracter;
Ingrese las horas trabajadas: 10
Escribir “Ingrese las horas trabajadas: ”;
Leer horas;
dia
10
14
Ingrese el código del turno: 3
Escribir “Ingrese el código del turno: ”;
3
Leer turno;
Ingrese el código del día: n
Escribir “Ingrese el código del día: ”;
“n”
Leer dia;
¿turno = 3? -> SI
50
jornal <- 5 * horas;
El jornal del operario es: 50
Escribir “El jornal del operario es: “, jornal;
Ejecución 4:
Instrucción
Definir horas, turno, jornal Como Entero;
horas
turno
⊥
⊥
dia
jornal
Pantalla
⊥
⊥
Definir dia Como Caracter;
Ingrese las horas trabajadas: 7
Escribir “Ingrese las horas trabajadas: ”;
7
Leer horas;
Ingrese el código del turno: 1
Escribir “Ingrese el código del turno: ”;
1
Leer turno;
Ingrese el código del día: d
Escribir “Ingrese el código del día: ”;
“d”
Leer dia;
¿turno = 3? -> NO
¿turno = 2? -> NO
¿dia <> “d”? -> NO
21
jornal <- (2 + 1) * horas;
El jornal del operario es: 21
4.3.2.2 Condicional Múltiple
Con frecuencia existen más de dos alternativas posibles, por ejemplo, en una ecuación de segundo
grado el discriminante puede ser negativo, nulo o positivo. Este problema se puede resolver
utilizando estructuras alternativas simples o dobles anidadas o en cascada, pero este tipo de solución
añade complejidad al algoritmo y hace difícil la lectura del algoritmo.
La estructura condicional múltiple ofrece una solución más simple y compacta. Para esta estructura
se consulta el valor almacenado en una variable que puede tomar n valores enteros distintos (1, 2,
3,..., n). A cada valor corresponde una acción (o conjunto de acciones) diferente, lo que significa que
el flujo de ejecución seguirá un camino distinto entre los n posibles caminos dependiendo del valor
de la variable de control.
En el LDA la estructura condicional múltiple se escribe:
Segun <variable> Hacer
<número1>: <acciones1>
<número2>, <número3>: <acciones2>
<...>
<númeron>: <accionesn>
De Otro Modo: <accionesO>
FinSegun
15
El diagrama de flujo correspondiente es el siguiente:
valor <variable>?
<número2>,
<número1>:
<número3>:
<acciones1>
<acciones2>
<númeron>:
...
De Otro Modo:
<accionesn>
<accionesO>
Cada opción está formada por uno o más números separados por comas, dos puntos y una secuencia
de acciones. Si una opción incluye varios números, la secuencia de instrucciones asociada se debe
ejecutar cuando el valor de la variable es igual a uno de esos números.
Opcionalmente, se puede agregar una opción final (De Otro Modo), cuya secuencia de instrucciones
asociada se ejecutará sólo si el valor almacenado en la variable no coincide con ninguna de las
opciones anteriores.
Si analizamos el algoritmo anterior (Jornales) podemos observar que el cálculo del jornal depende
del turno que puede tomar los valores 1, 2 ó 3. Por lo tanto, estamos ante un problema que puede
resolverse usando una selección múltiple y podemos reescribir dicho algoritmo de la siguiente
manera:
Proceso Jornales
Definir horas, turno, jornal Como Entero;
Definir dia Como Caracter;
Segun turno Hacer
1: Si dia <> “d” Entonces
jornal <- 2 * horas;
Sino
jornal <- (2 + 1) * horas;
FinSi
2: jornal <- 3 * horas;
3: jornal <- 5 * horas;
De Otro Modo: Escribir “Ingresó un turno inválido”;
jornal <- 0;
FinSegun
Escribir jornal;
FinProceso
Si analizamos los dos algoritmos vemos que el último es más compacto y claro. En este caso se usó
la opción De Otro Modo para avisarle al usuario que ingresó un valor de turno inválido. ¿Por qué fue
16
necesario asignar un valor cero a la variable jornal? Porque si el usuario hubiese ingresado un valor
inválido para turno no se le hubiere asignado ningún valor a dicha variable, es decir, jornal tendría
un valor indefinido y al querer imprimir su valor el procesador se detendría y daría un error.
Ejemplo:
Enunciado: Un banco ha decidido aumentar el límite de crédito de las tarjetas de crédito de sus
clientes. Para esto considera que si su cliente tiene tarjeta tipo 1, el aumento será de 25%; si tiene
tipo 2, será de 35%; si tiene tipo 3, de 40% y para cualquier otro tipo, de 50%.
Se solicita diseñar un algoritmo en LDA y representar su diagrama de flujo para determinar el nuevo
límite de crédito que tendrá una persona en su tarjeta.
Ambiente del algoritmo:
Objeto
Tipo
Descripción
TT
Variable de entrada, de tipo entero
Almacena el tipo de tarjeta.
LA
Variable de entrada, de tipo real
Almacena el límite actual de crédito.
AC
Variable de auxiliar, de tipo real
Almacena el aumento de crédito.
NL
Variable de salida, de tipo real
Almacena el nuevo límite de crédito.
Notar que las variables que se utilicen dentro del algoritmo para realizar cálculos y que no sean de
entrada y/o de salida son consideradas variables auxiliares. En el ambiente anterior, AC es una
variable auxiliar que se utiliza para almacenar el aumento de crédito.
La solución de este problema se puede plantear con un condicional múltiple, dado que el elemento
selector, que es el tipo de tarjeta (TT), es de tipo entero.
Algoritmo:
Versión 1:
t1. Definir las variables a ser utilizadas por el algoritmo.
t2. Leer datos de entrada.
t3. Calcular el aumento de límite de crédito.
t4. Mostrar el nuevo límite.
Versión 2:
t1. Definir las variables a ser utilizadas por el algoritmo.
t2.1. Leer el tipo de tarjeta (TT).
t2.2. Leer el límite actual de crédito (LA).
t3. Según el tipo de tarjeta ingresado:
t3.1. TT = 1, calcular aumento del 25%
t3.2. TT = 2, calcular aumento del 35%
t3.3. TT = 3, calcular aumento del 40%
17
t3.4. En otro caso, calcular aumento del 50%
t4.1. Calcular el nuevo límite.
t4.2. Mostrar por pantalla el nuevo límite.
Versión 3 (final):
Proceso Aumento_Tarjeta
//t1.
Definir TT Como Entero;
Definir LA, AC, NC Como Real;
//t2.1.
Escribir “Ingrese el tipo de tarjeta: ”;
Leer TT;
//t2.2.
Escribir “Ingrese el límite actual de crédito: ”;
Leer LA;
Segun TT Hacer
//t3.1.
1: AC <- LA * 0.25;
//t3.2.
2: AC <- LA * 0.35;
//t3.3.
3: AC <- LA * 0.40;
//t3.4.
De Otro Modo: AC <- LA * 0.50;
FinSegun
//t4.1.
NL <- LA + AC;
//t4.2.
Escribir “El nuevo límite de crédito es: “, NL;
FinProceso
Supongamos que queremos ejecutar cuatro veces el algoritmo Jornales con los siguientes datos de
entrada (estos valores se almacenarán en las variables al ejecutarse las instrucciones de lectura):
Ejecución 1
Ejecución 2
TT:
2
TT:
5
LA:
1000
LA:
2000
Ejecución 1:
Instrucción
Definir TT Como Entero;
TT
LA
AC
NC
Pantalla
⊥
18
⊥
Definir LA, AC, NC Como Real;
⊥
⊥
Ingrese tipo de tarjeta: 2
Escribir “Ingrese el tipo de tarjeta: ”;
2
Leer TT;
Ingrese el límite actual de crédito:
1000
Escribir “Ingrese el límite actual de
crédito: ”;
1000
Leer LA;
¿TT = 1? -> NO
¿TT = 2? -> SI
350
AC <- LA * 0.35;
1350
NL <- LA + AC;
Escribir “El nuevo límite de crédito es: “,
El nuevo límite de crédito es: 1350
NL;
Ejecución 2:
Instrucción
Definir TT Como Entero;
TT
LA
AC
NC
⊥
⊥
⊥
⊥
Definir LA, AC, NC Como Real;
Ingrese tipo de tarjeta: 5
Escribir “Ingrese el tipo de tarjeta: ”;
Leer TT;
5
Ingrese el límite actual de crédito:
2000
Escribir “Ingrese el límite actual de
crédito: ”;
Leer LA;
Pantalla
2000
¿TT = 1? -> NO
¿TT = 2? -> NO
¿TT = 3? -> NO
AC <- LA * 0.50;
NL <- LA + AC;
Escribir “El nuevo límite de crédito es: “,
1000
3000
El nuevo límite de crédito es: 2000
NL;
19
Hasta el momento, las soluciones planteadas a los problemas propuestos han sido para una persona,
un objeto o cosa, pero siempre de manera unitaria. Sin embargo, debemos considerar que cuando se
plantean problemas como calcular un sueldo cabe la posibilidad de que el cálculo se tenga que hacer
para dos o más empleados. Si bien es un proceso de cálculo que por lógica debe ser el mismo para
cada uno, puede existir la posibilidad de que los datos que determinan ese sueldo sean los que
cambien.
También se puede considerar el problema de calcular el monto de una llamada realizada por una
persona, pero también se pueden considerar N llamadas efectuadas por la misma persona, donde lo
que puede cambiar es el tiempo, o la tarifa, lo cual puede depender de alguna condición. De igual
forma se pueden presentar muchos casos donde el proceso se debe repetir varias veces. Por tal
motivo se emplean estructuras denominadas repetitivas, de ciclo o de bucle, e independientemente
del nombre que se les aplique, lo que importa es que permiten que un proceso pueda realizarse N
veces, donde sólo cambien los datos que se utilizan en el proceso.
4.3.3 Estructura de Control de Repetición
Las estructuras de repetición permiten la ejecución de una lista o secuencia de acciones o
instrucciones en forma iterativa o repetitiva.
El número de veces que la secuencia de acciones se ejecutará se puede especificar de manera
explícita o a través de una condición lógica. A cada ejecución de la secuencia de acciones se le
conoce como una iteración.
Existen tres tipos principales de estructuras de repetición: la estructura Mientras-Hacer, la estructura
y la estructura Para-Hasta.
Repetir-Hasta Que
El objetivo de esta teoría es presentar las diferentes estructuras de repetición, analizar las diferencias
entre ellas y reconocer la conveniencia de uso de cada una de ellas.
4.3.3.1 Estructura de repetición Mientras-Hacer
El formato de esta estructura de control en el LDA es:
Mientras <condición> Hacer
<acciones>;
FinMientras
En esta estructura de control la palabra FinMientras es un delimitador que se utiliza para indicar el
fin de la secuencia de acciones a repetir. La cantidad de veces que se ejecutará las <acciones> o el
cuerpo de la repetición es 0, 1, 2, ..., n. Dicha cantidad no es conocida de antemano sino que depende
del valor de verdad de la <condición>.
La <condición> es evaluada antes de la ejecución de la secuencia <acciones>. Si el resultado es
verdadero, <acciones> se ejecuta y luego, se vuelve a evaluar la <condición>; si dicha condición
resulta falsa, finaliza la repetición, es decir, se ejecutará la primera acción primitiva que siga a
FinMientras (si ésta existe).
En el caso en que la condición evalúe la primera vez como falsa, la secuencia de acciones no será
ejecutada, lo cual quiere decir que el número de repeticiones o iteraciones de este bloque será cero.
Si la condición siempre evalúa a verdadero, la secuencia de acciones se ejecutará indefinidamente, es
20
decir, un número infinito de veces. A fin de evitarlo, las instrucciones del cuerpo del ciclo deben
contener alguna acción que modifique la o las variables involucradas en la condición, de modo que
ésta, en algún momento deje de ser verdadera y así finalice la ejecución del ciclo.
El correspondiente diagrama de flujo es:
<condición>
F
V
<acciones>
Ejemplo:
Enunciado: Se requiere un algoritmo en LDA para obtener la suma de cinco números enteros
ingresados por teclado.
Ambiente del algoritmo:
Objeto
Tipo
C
Variable de auxiliar, de tipo entero
Se utiliza como contador de 5 números.
nro
Variable de entrada, de tipo entero
Se utiliza para almacenar cada número
entero ingresado por teclado.
Variable de salida, de tipo entero
Se utiliza para almacenar la suma de los 5
números ingresados por teclado.
suma
Descripción
Algoritmo:
Versión 1:
t1. Definir las variables a ser utilizadas por el algoritmo.
t2. Inicializar la variable contador C y la variable suma.
t3. Mientras no se hayan ingresado 5 números, solicitar un número por teclado (nro) y actualizar el
valor de suma, sumando su valor actual con el valor actual de nro.
t4. Mostrar la suma de los 5 números ingresados.
Versión 2:
t1. Definir las variables a ser utilizadas por el algoritmo.
t2.1. C<-1;
t2.1. suma<-0;
21
t3. Mientras C<=5 Hacer
t3.1. Solicitar un número y almacenarlo en nro.
t3.2. Actualizar suma, sumando su valor actual con el valor actual de nro.
t3.3. Incrementar en 1 la variable C.
t4. Mostrar el contenido de la variable suma.
Versión 3 (final):
Proceso Suma_de_5_nros
//t1.
Definir C, nro, suma Como Entero;
//t2.1.
C <- 1;
//t2.2.
suma <- 0;
//t3.
Mientras C<=5 Hacer
//t3.1.
Escribir “Ingrese un número entero: ”;
Leer nro;
//t3.2.
suma <- suma + nro;
//t3.3.
C <- C + 1;
FinMientras
//t4.
Escribir “La suma de los 5 números ingresados es: “, suma;
FinProceso
Se puede observar que el contador del ciclo C se inicializa en uno, posteriormente se verifica que éste
sea menor o igual a 5, que es la cantidad de veces que se deben ejecutar las acciones del cuerpo de la
iteración (cinco veces). Dentro del cuerpo de la iteración, se lee un nuevo valor en nro, se acumula
en suma y el contador se incrementa en 1.
En general, toda iteración debe tener un valor inicial, un incremento y un verificador que establezca
el límite de ejecución.
Vamos a realizar una ejecución para el algoritmo Suma_de_5_nros con los siguientes datos de
entrada: 5 8 4 3 5.
Instrucción
Definir C, nro, suma Como Entero;
C <- 1;
suma <- 0;
C
nro
suma
⊥
⊥
⊥
Pantalla
1
0
¿C<=5? -> SI
22
Ingrese un número entero: 5
Escribir “Ingrese un número entero:”;
5
Leer nro;
5
suma <- suma + nro;
2
C <- C + 1;
¿C<=5? -> SI
Ingrese un número entero: 8
Escribir “Ingrese un número entero:”;
8
Leer nro;
13
suma <- suma + nro;
3
C <- C + 1;
¿C<=5? -> SI
Ingrese un número entero: 4
Escribir “Ingrese un número entero:”;
4
Leer nro;
17
suma <- suma + nro;
4
C <- C + 1;
¿C<=5? -> SI
Ingrese un número entero: 3
Escribir “Ingrese un número entero:”;
3
Leer nro;
20
suma <- suma + nro;
5
C <- C + 1;
¿C<=5? -> SI
Ingrese un número entero: 5
Escribir “Ingrese un número entero:”;
5
Leer nro;
25
suma <- suma + nro;
6
C <- C + 1;
¿C<=5? -> NO
Escribir “La suma de los 5 números ingresados
es: “, suma;
La suma de los 5 números ingresados
es: 25
4.3.3.2 Estructura de repetición Repetir-Hasta Que
El formato de esta estructura de control en el LDA es:
Repetir
<acciones>;
Hasta Que <condición>
La instrucción Repetir-Hasta Que ejecuta una secuencia de instrucciones (<acciones>) hasta que la
<condición> sea verdadera.
Al ejecutarse esta estructura de repetición, las <acciones> que forman el cuerpo de la repetición se
23
ejecutan una vez y luego se evalúa la <condición>. Si la condición es falsa, el cuerpo del ciclo se
ejecuta nuevamente y se vuelve a evaluar la condición. Esto se repite hasta que la condición sea
verdadera.
Notar que, dado que la condición se evalúa al final, las acciones del cuerpo del ciclo siempre serán
ejecutadas al menos una vez.
Además, a fin de evitar repeticiones infinitas, el cuerpo del ciclo debe contener alguna acción que
modifique a la o las variables involucradas en la condición de modo que en algún momento la
condición sea verdadera y finalice la ejecución del ciclo.
El diagrama de flujo correspondiente a esta estructura es el siguiente:
<acciones>
<condición>
V
F
Supongamos ahora que se solicita realizar un algoritmo en LDA para obtener la suma de cinco
números enteros ingresados por teclado pero utilizando la estructura de repetición Repetir-Hasta
Que.
El ambiente y las versiones 1 y 2 del algoritmo Suma_de_5_nros serían similares, sólo cambiaría la
versión final.
Versión 3 (final):
Proceso Suma_de_5_nros_con_RepetirHastaQue
//t1.
Definir C, nro, suma Como Entero;
//t2.1.
C <- 1;
//t2.2.
suma <- 0;
//t3.
Repetir
Escribir “Ingrese un número entero: ”;
Leer nro;
suma <- suma + nro;
C <- C + 1;
Hasta Que C > 5
//t4.
24
Escribir “La suma de los 5 números ingresados es: “, suma;
FinProceso
Como ejercicio, realizar la ejecución del algoritmo Suma_de_5_nros_con_RepetirHastaQue con los
mismos datos que se ejecutó el algoritmo Suma_de_5_nros y observar que se obtienen los mismos
resultados.
Muchas veces en nuestros algoritmos es necesario realizar una validación de los datos ingresados por
los usuarios antes de realizar cualquier acción. La validación no es más que determinar si el valor(es)
ingresado(s) cumple(n) con alguna(s) característica(s).
Por ejemplo, validar que un valor ingresado por el usuario esté en un rango (mayor que 0 y menor
que 70).
Las validaciones se las puede hacer a través de ciclos repetitivos. Uno de los que puede ser empleado
es el Repetir-Hasta Que.
Ejemplo:
Elaborar un algoritmo en LDA que reciba como entrada un número y verifique si es un número
comprendido entre 0 y 10; sino es así, se debe volver a solicitar un número hasta que se ingrese un
valor correcto.
Ambiente del algoritmo:
Objeto
Tipo
nro
Variable de entrada, de tipo entero
Descripción
Almacena el número a validar.
Algoritmo:
Versión 1:
t1. Definir la variable a ser utilizada por el algoritmo.
t2. Hasta que no se ingrese un número mayor o igual a 0 y menor o igual a 10, volver a solicitar un
número.
t3. Mostrar el cartel “Número correcto”.
Versión 2 (final):
Proceso Validacion
//t1.
Definir nro Como Entero;
//t2.
Repetir
Escribir “Ingrese un número: ”;
Leer nro;
Hasta Que nro >= 0 & nro <= 10
//t3.
25
Escribir “Número correcto”;
FinProceso
Supongamos que en una ejecución del algoritmo el usuario ingresa los siguientes números -15 12 7.
Entonces la ejecución del algoritmo será:
Instrucción
Definir nro Como Entero;
nro
Pantalla
⊥
Ingrese un número: -15
Escribir “Ingrese un número: ”;
-15
Leer nro;
¿nro >= 0 & nro <= 10? -> NO
Ingrese un número: 12
Escribir “Ingrese un número: ”;
12
Leer nro;
¿nro >= 0 & nro <= 10? -> NO
Ingrese un número: 7
Escribir “Ingrese un número: ”;
7
Leer nro;
¿nro >= 0 & nro <= 10? -> SI
Escribir “Número correcto”;
Número correcto
4.3.3.3 Estructura de repetición Para-Hasta
El formato de esta estructura de control en el LDA es:
Para <variable> <- <inicial> Hasta <final> [Con Paso <paso>] Hacer
<acciones>;
FinPara
Esta estructura de control repetitiva se emplea cuando se sabe de antemano cuántas veces se
repetirán las acciones que conforman el cuerpo de la repetición (<acciones>). Al ingresar a la
estructura, la variable <variable> (llamada variable de control de la repetición) recibe el valor inicial
<inicial> y se evalúa si el valor almacenado en <variable> alcanzó el valor final indicado por
<final>. Si esto no así, se ejecutan las <acciones> que forman el cuerpo del ciclo. Luego, se
incrementa la variable <variable> en <paso> unidades y se vuelve a evaluar la condición. Si ésta es
falsa se repite hasta que <variable> alcance al valor <final>. Los [ ] que encierran a [Con Paso
<paso>] (en la definición de la estructura) se interpreta como que la cláusula puede escribirse o no,
es decir, que es opcional. Si se omite la cláusula Con Paso <paso>, la variable <variable> se
incrementará automáticamente en 1. <paso> puede ser un valor positivo o negativo y puede estar
determinado por una constante o variable de tipo entero.
El diagrama de flujo correspondiente es:
26
<variable> <- <inicial>
<variable> no alcanzó
el valor <final>?
(*)
(*)
F
V
<acciones>
Incrementar <variable>
(*)
(*) Estas acciones se realizan automáticamente. No se debe inicializar, ni incrementar explícitamente
la variable de control <variable> y tampoco escribir la condición.
Recomendación: no modificar la variable de control <variable> en ninguna de las acciones que
forman las <acciones> del ciclo Para-Hasta. Recuerde que en el propio ciclo se define el <paso>.
Supongamos que necesitamos una estructura de repetición Para-Hasta que muestre los números
enteros comprendidos entre el 1 y el 10 en orden ascendente. La estructura y su correspondiente
diagrama de flujo se muestran a continuación:
I <- 1
I <= 10
F
Para I <- 1 Hasta 10 Hacer
Escribir I;
FinPara
V
Escribir I;
I <- I + 1;
27
Supongamos ahora que necesitamos mostrar los números enteros comprendidos entre el 1 y el 10 en
orden descendente. Como en la definición de la estructura de repetición Para-Hasta podemos utilizar
<paso> para incrementar la variable de control, en este caso <paso> puede ser -1 para realizar la
muestra de los números en orden descendente. La estructura y su correspondiente diagrama de flujo
se muestran a continuación:
I <- 10;
I >= 1
F
Para I <- 10 Hasta 1 Con Paso -1 Hacer
Escribir I;
FinPara
V
Escribir I;
I <- I + (-1);
Notar que, a diferencia del ejercicio de la muestra ascendente, al tener un paso negativo la condición
(que se genera automáticamente) evalúa por >=.
¿Y si quisiéramos mostrar los números pares comprendidos entre el 1 y el 10? Podríamos utilizar
<inicial> igual a 2 y el <paso> igual a 2 para recorrer los números pares. La estructura y su
correspondiente diagrama de flujo se muestran a continuación:
I <- 2;
I <= 10
F
Para I <- 2 Hasta 10 Con Paso 2 Hacer
Escribir I;
FinPara
V
Escribir I;
I <- I + 2;
Verificar que los valores mostrados por pantalla son 2, 4, 6, 8, 10.
28
Supongamos ahora que se solicita realizar un algoritmo en LDA para obtener la suma de cinco
números enteros ingresados por teclado pero utilizando la estructura de repetición Para-Hasta.
El ambiente y las versiones 1 y 2 del algoritmo Suma_de_5_nros serían similares, sólo cambiaría la
versión final.
Versión 3 (final):
Proceso Suma_de_5_nros_con_ParaHasta
//t1.
Definir C, nro, suma Como Entero;
//t2.1. No se necesita esta tarea ya que C pasaría a ser la variable de control de la estructura y se
// inicializa automáticamente
//t2.2.
suma <- 0;
//t3.
Para C <- 1 Hasta 5 Hacer
Escribir “Ingrese un número entero: ”;
Leer nro;
suma <- suma + nro;
FinPara
//t4.
Escribir “La suma de los 5 números ingresados es: “, suma;
FinProceso
Como ejercicio, realizar la ejecución del algoritmo Suma_de_5_nros_con_ParaHasta con los mismos
datos que se ejecutó el algoritmo Suma_de_5_nros y observar que se obtienen los mismos resultados.
Ejemplo:
Enunciado: Dados 10 números enteros ingresados por el usuario se pide diseñar un algoritmo en
LDA que calcule por separado el promedio de los números pares y el producto de los impares,
mostrando como salida el promedio, el producto y además la cantidad de números pares e impares
ingresados.
Ambiente del algoritmo:
Objeto
I
num
cpares
cimpares
Tipo
Descripción
Variable de control, de tipo entero
Sirve como variable de control de la
estructura Para-Hasta.
Variable de entrada, de tipo entero
Almacena los números ingresados por
el usuario.
Variable de salida, de tipo entero
Almacena la cantidad de números
pares ingresados.
Variable de salida, de tipo entero
Almacena la cantidad de números
impares ingresados.
29
spares
pimpares
Variable auxiliar, de tipo entero
Almacena la suma de los números
pares.
Variable auxiliar, de tipo entero
Almacena el producto de los números
impares.
Algoritmo:
Versión 1:
t1. Definir las variables a ser utilizadas por el algoritmo.
t2. Inicializar las variables que correspondan.
t3. Hasta que no se hayan ingresado 10 números enteros
t3.1. Solicitar un número entero.
t3.2. Si el número es par entonces incrementar en uno el contador de números pares y sumar el
número par sino incrementar en uno el contador de números impares y calcular el producto de los
números impares.
t4. Imprimir la cantidad de números pares y su valor promedio.
t5. Imprimir la cantidad de números impares y su producto.
Versión 2 (final):
Proceso SumaYPromedio
// t1.
Definir I, num, cpares, cimpares, spares, pimpares Como Entero;
// t2.
cpares <- 0;
cimpares <- 0;
spares <- 0;
pimpares <- 1;
// t3.
Para I <- 1 Hasta 10 Con Paso 1 Hacer
//t3.1.
Escribir “Ingrese un número: ”;
Leer num;
// t3.2.
Si num % 2 = 0 Entonces
cpares <- cpares + 1;
spares <- spares + num;
Sino
cimpares <- cimpares + 1;
pimpares <- pimpares * num;
FinSi
FinPara
// t4.
30
Escribir “Cantidad de números pares: ”, cpares;
Escribir “Valor promedio de los números pares: ” , spares / cpares;
// t5.
Escribir “Cantidad de números impares: ”, cimpares;
Escribir “Producto de los números impares: ”, pimpares;
FinProceso
Supongamos que en una ejecución del algoritmo el usuario ingresa los siguientes números 8 9 15 -20
10 2 120 5 -1 50. Entonces la ejecución del algoritmo será:
Tarea
Definir I, num, cpares, cimpares,
I
⊥
num cpares cimpares spares pimpares
⊥
⊥
⊥
⊥
Pantalla
⊥
spares, pimpares Como Entero;
0
cpares <- 0;
0
cimpares <- 0;
0
spares <- 0;
1
pimpares <- 1;
I <- 1
1
¿I <= 10? -> SI
Ingrese un número: 8
Escribir “Ingrese un número: ”;
8
Leer num;
¿num % 2 = 0? -> SI
1
cpares <- cpares + 1;
8
spares <- spares + num;
FinPara
2
¿I <= 10? -> SI
Ingrese un número: 9
Escribir “Ingrese un número: ”;
9
Leer num;
¿num % 2 = 0? -> NO
1
cimpares <- cimpares + 1;
9
pimpares <- pimpares * num;
FinPara
3
¿I <= 10? -> SI
Ingrese un número: 15
Escribir “Ingrese un número: ”;
15
Leer num;
¿num % 2 = 0? -> NO
2
cimpares <- cimpares + 1;
135
pimpares <- pimpares * num;
FinPara
… (se continúa con la ejecución hasta
la décima iteración)
FinPara
4
9
-1
5
4
120
-675
10
31
¿I <= 10? -> SI
Ingrese un número: 50
Escribir “Ingrese un número: ”;
50
Leer num;
¿num % 2 = 0? -> SI
6
cpares <- cpares + 1;
170
spares <- spares + num;
11
FinPara
¿I <= 10? -> NO
Escribir “Cantidad de números pares: ”,
cpares;
Escribir “Valor promedio de los
números pares: ” , spares / cpares;
Escribir “Cantidad de números impares:
”, cimpares;
Escribir “Producto de los números
impares: ”, pimpares;
Cantidad de números
pares: 6
Valor promedio de los
números pares: 28.33
Cantidad de números
impares: 4
Producto de los
números impares: -675
En el ejemplo sólo se pidieron como entrada 10 enteros, pero también podría haberse solicitado que
el usuario ingrese además la cantidad de enteros que desea ingresar y almacenar esta cantidad en la
variable N. ¿Qué parte del algoritmo anterior se modificaría?
También usaremos este ejemplo para ejemplificar dos usos comunes de una variable: como contador
y acumulador.
Contador
Es una variable cuyo valor se modifica en una unidad constante cada vez que ocurre un evento. La
modificación consiste en incrementar o decrementar el valor del contador. Se debe inicializar el
contador antes de utilizarlo.
En el algoritmo SumaYPromedio se utilizaron dos variables con esta finalidad: cpares y cimpares las
cuales fueron inicializadas en cero antes del ingreso a la estructura Para-Hasta y luego en cada
iteración fueron incrementadas en uno cuando correspondía. ¿Por qué fue necesario inicializarlas con
un valor cero?
Resumiendo el uso de un contador implica la realización de las siguientes operaciones:
● Inicialización:
contador <- valor_inicial;
● Incremento:
contador <- contador + constante;
ó
● Decremento:
contador <- contador - constante;
Acumulador
32
Es una variable cuyo valor se modifica, en una cantidad variable, cada vez que ocurre un evento. La
modificación puede ser incrementar o decrementar su valor. Al igual que los contadores, los
acumuladores deben ser inicializados antes de utilizarse.
En el algoritmo SumaYPromedio utilizamos dos variables como acumuladores spares y pimpares, las
cuales fueron inicializadas con 0 y 1 respectivamente ¿Por qué se inicializaron con valores distintos?
En spares se fue acumulando la suma de los números pares y en pimpares el producto de los
números impares.
Resumiendo, las operaciones que se realizan sobre un acumulador son:
● Inicialización
acumulador <- valor_inicial;
● Sumador (incremento)
acumulador <- acumulador + valor;
ó
● Restador (decremento)
acumulador <- acumulador – valor;
ó
● Multiplicador (incremento)
acumulador <- acumulador * valor;
ó
● Divisor (decremento)
acumulador <- acumulador / valor;
Ya definidas las distintas estructuras de repetición, analizaremos a través de un ejemplo la
correspondencia que existe entre ellas.
4.3.3.4 Correspondencia entre ciclos
En la teoría matemática de programación sólo es necesario un tipo de estructura de repetición. En
esta sección se explican las correspondencias que hacen posible esta afirmación, tomando como ciclo
de referencia la estructura Mientras.
Correspondencia entre el ciclo Mientras-Hacer y el ciclo Repita-Hasta Que
La diferencia fundamental entre las iteraciones realizadas con la estructura Mientras-Hacer y
Repita-Hasta Que, es que en el segundo se ejecuta por lo menos una vez las <acciones> del cuerpo
de la iteración, mientras que en el primero existe la posibilidad de que no se ejecute alguna vez.
El ejecutar las <acciones> una vez antes del ciclo Mientras-Hacer y negar la <condición> permite
modelar un ciclo Repita-Hasta Que, es decir:
33
Repetir
<acciones>
Hasta Que <condición>
<acciones>
Mientras ¬<condición> Hacer
<acciones>
FinMientras
Correspondencia entre el ciclo Para-Hasta y el ciclo Mientras-Hacer
Formalmente, un ciclo Para-Hasta es una forma abreviada de un ciclo Mientras-Hacer, precedido por
una asignación y que en cada iteración incrementa una variable. Por lo tanto, el siguiente ciclo ParaHasta:
Para <variable> <- <inicial> Hasta <final> [Con Paso <paso>] Hacer
<acciones>;
FinPara
es una forma abreviada de:
a) Con paso positivo
b) Con paso negativo
<variable> <- <inicial>;
<variable> <- <inicial>;
Mientras <variable> <= <final> Hacer
Mientras <variable> >= <final> Hacer
<acciones>;
<acciones>;
<variable> <- <variable> + <paso>;
<variable> <- <variable> + <paso>;
FinMientras
FinMientras
Si al usar la estructura Para-Hasta se omite el paso, en el Mientras-Hacer debe incrementarse en 1 la
<variable>, es decir, <variable> <- <variable> + 1;.
El siguiente ejemplo se resuelve usando las distintas estructuras de repetición. Verificar que tienen el
mismo comportamiento.
Ejemplo:
Diseñar un algoritmo en LDA que imprima los números pares en orden descendente entre 1 y 100.
Solución 1
Proceso Ejemplo
Solución 2
Proceso Ejemplo
Solución 3
Proceso Ejemplo
Definir I Como Entero;
Definir I Como Entero;
Definir I Como Entero;
Para I <- 100 Hasta 2 Con Paso -2 Hacer
I <- 100;
I <- 100 ;
Mientras I >= 2 Hacer
Repetir
Escribir I ;
FinPara
Escribir I ;
Escribir I ;
FinProceso
I <- I - 2 ;
I <- I – 2 ;
FinMientras
FinProceso
Hasta Que I < 2
FinProceso
4.3.3.5 ¿Cuándo usar estructuras de control definido o indefinido?
34
La estructura de repetición Para-Hasta se conoce comúnmente como estructura de control
definido, ya que los valores iniciales y finales especificados para la variable contadora que controla
el ciclo determina de manera exacta el número de veces que se ejecuta el mismo. Tanto el valor
<inicial> como el <final> pueden estar determinados utilizando constantes de tipo entero o variables
de tipo entero. Cuando se utilicen variables, se debe asegurar que almacenen valores válidos.
Para utilizar un ciclo Para-Hasta, al resolver un algoritmo se debe determinar el número exacto de
veces que se va a ejecutar el ciclo. En el ejemplo anterior de calcular los números pares desde 2 a
100, se conoce el límite inferior y superior de la repetición y el paso, entonces se sabe que se
ejecutará exactamente 50 veces (¿por qué?).
Por otro lado, tanto la estructura Mientras-Hacer como Repita-Hasta Que se conocen como
estructuras de control indefinido, puesto que a priori no se conoce la cantidad de veces que se
ejecutarán porque dependen de una condición.
La estructura Mientras-Hacer permite ejecutar una secuencia de acciones mientras que la evaluación
de una expresión lógica de cómo resultado verdadero y dicha secuencia de acciones puede ejecutarse
cero o más veces.
La estructura Repita-Hasta Que permite ejecutar una secuencia de acciones por lo menos una vez.
Luego evalúa la condición y la secuencia de acciones sólo se ejecutará mientras la condición sea
falsa.
Anidamiento de estructuras de control repetitiva
De la misma forma que es posible incluir dentro de una estructura condicional otra estructura
condicional, también es posible insertar una estructura de repetición en el interior de otra estructura
de repetición. Las reglas de anidamiento son similares en ambos casos: la estructura interna debe
estar totalmente contenida dentro de la estructura externa, no permitiéndose el solapamiento.
A continuación se presentan distintos ejemplos del uso de estructuras de control anidadas:
Ejemplo:
Enunciado: Se conoce la población de cada una de las cinco ciudades más importantes de veintiocho
países y se desea identificar e imprimir la población de la ciudad más grande (en número de
habitantes) de cada país. El tamaño de la población de cada ciudad es un dato ingresado por el
usuario.
Ambiente del algoritmo:
Claramente se desprende del enunciado que vamos a necesitar dos repeticiones. Ambas con número
de repeticiones conocidas: una repetición para controlar los 28 países y otra para controlar las 5
ciudades más importantes de cada país. Por lo tanto podemos utilizar dos estructuras de repetición
del tipo Para-Hasta, que tendrán dos variables de control, una para cada ciclo: J para controlar el
número de país y K para controlar el número de ciudad. Además se necesita una variable para ir
guardando el tamaño de población de cada ciudad, que podemos llamar tampobl y una variable para
guardar el tamaño de la mayor ciudad (en cantidad de habitantes) de cada país, que llamaremos
mayor.
Sintetizando el ambiente sería:
Objeto
Tipo
Descripción
35
J
K
tampobl
Variable de control, de tipo entero
Controla la repetición del número de
país.
Variable de control, de tipo entero
Controla la repetición del número de
ciudad.
Variable de entrada, de tipo entero
Contiene la cantidad de habitantes de
cada ciudad.
Variable de salida, de tipo entero
Contiene la cantidad de habitantes de
la ciudad de mayor tamaño para un
país dado.
mayor
Algoritmo:
Versión 1:
t1. Definir las variables a ser utilizadas por el algoritmo.
t2. Mientras no se hayan ingresado los datos para los 28 países
t2.1. Inicializar mayor (mayor<-0;)
t2.2. Mientras no se hayan ingresado las 5 ciudades más importantes de cada país
t2.2.1. Solicitar tamaño de población (tampobl)
t2.2.2. Si tamaño de población ingresado es mayor que mayor entonces mayor <tampobl
t2.3. Informar el mayor número de habitantes de las ciudades del país ingresado.
Versión 2 (final):
Proceso Ciudades
//t1.
Definir J, K, tampobl, mayor Como Entero;
//t2.
Para J <- 1 Hasta 28 Hacer
//t2.1.
mayor <- 0 ;
//t2.2.
Para K <- 1 Hasta 5 Hacer
//t2.2.1.
Escribir “Ingrese tamaño de población”;
Leer tampobl;
//t2.2.2.
Si tampobl > mayor Entonces
mayor <- tampobl;
FinSi
FinPara
//t2.3.
Escribir “El mayor número de habitantes del país ”, J ,“ es: ” ,tampobl;
36
FinPara
FinProceso
En el algoritmo anterior notar que en ambos Para-Hasta se omitió el paso ya que cuando se omite la
variable de control se incrementa automáticamente en 1.
Queda como actividad para el alumno construir una tabla de ejecución para el algoritmo Ciudades.
Se sugiere usar para la prueba 4 países y 3 ciudades para cada país, quedando a su elección el tamaño
de cada ciudad.
Ejemplo:
Enunciado: Diseñar un algoritmo en LDA que permita encontrar los tres primeros números perfectos.
Un número es perfecto cuando la suma de sus divisores enteros positivos (menores a sí mismo) es
igual al número considerado. Por ejemplo, el número 6 es perfecto porque sus divisores son 1, 2, 3 y
su suma es 1+2+3 = 6.
Necesitamos encontrar los 3 primeros números perfectos pero no sabemos cuánto vamos a iterar
hasta encontrarlos. Esto nos lleva a usar una estructura de repetición Mientras-Hacer porque no
podemos usar una estructura Para-Hasta. Este Mientras-Hacer estará controlado por la cantidad de
números perfectos (variable cuentanp) que encuentre. Además vemos que el problema no requiere
de ningún dato de entrada. Por lo tanto, debemos ir generando los números (variable numgen) y para
cada uno de ellos verificar si es o no perfecto. Para hacer esto debo calcular sus divisores (variable
div) e ir sumándolos (variable sumdiv) y ¿cuántas veces debo hacer esto? Comenzar por el divisor 1
hasta el número generado menos 1, entonces esto lo podemos hacer usando un Para-Hasta que tiene
como variable de control a div y al terminar el Para-Hasta controlar si la suma de los divisores es
igual al número generado.
Ambiente del algoritmo:
Objeto
cuentanp
numgen
Tipo
Variable auxiliar, de tipo entero
Cuenta los números perfectos generados
(variable de control del Mientras-Hacer).
Variable auxiliar, de tipo entero
Contiene
generados.
Variable auxiliar, de tipo entero
Contiene los posibles divisores de los
números generados (variables de control
del Para-Hasta).
Variable auxiliar, de tipo entero
Contiene la suma de los divisores.
div
sumdiv
Descripción
los
distintos
números
Algoritmo:
Versión 1:
t1. Definir las variables a ser utilizadas por el algoritmo.
t2. Incializar la variable de control (cuentanp) del Mientras-Hacer en 1.
37
t3. Incializar la variable numgen en 0.
t4. Mientras no se hayan encontrado los 3 primeros números perfectos
t4.1. Generar número (numgen).
t4.2. Inicializar el sumador de divisores.
t4.3. Mientras no se encuentren los divisores de numgen desde 1 hasta numgen-1.
t4.3.1. Si es div es divisor de numgen entonces sumarlo en el sumador de los divisores
(sumdiv).
t4.4. Si la suma de los divisores es igual al número generado (numgen) entonces mostrar
e incrementar en 1 la variable de control del Mientras-Hacer.
numgen
Versión 2 (final):
Proceso TresPerfectos
//t1.
Definir cuentanp, div, numgen, sumdiv Como Entero;
//t2.
cuentanp <- 1;
//t3.
numgen <- 0;
//t4.
Mientras cuentanp <=3 Hacer
//t4.1.
numgen <- numgen + 1;
//t4.2.
sumdiv <- 0;
//t4.3.
Para div <- 1 Hasta numgen -1 Hacer
//t4.3.1.
Si numgen % div = 0 Entonces
sumdiv <- sumdiv+div;
FinSi
FinPara
//t4.4.
Si sumdiv = numgen Entonces
Escribir numgen;
cuentanp <- cuentanp +1 ;
FinSi
FinMientras
FinProceso
Verificar (utilizando PSeInt) que el algoritmo propuesto genera la siguiente salida 6 28 496.
El Mientras-Hacer más externo ¿podría reemplazarse por un Repetir-Hasta Que? Piense como
justificaría su respuesta y escriba el algoritmo alternativo.
Ejemplo:
38
Enunciado: Una empresa vende 5 artículos distintos, identificados con los códigos 1 a 5. La empresa
desea conocer los montos de venta de cada artículo por día y el monto total de la venta diaria (es
decir de todos los artículos). El algoritmo debe dar la posibilidad de ingresar más de un día a
voluntad del usuario. También se debe controlar que el código de artículo ingresado sea correcto.
En un ejemplo anterior hemos visto una de las formas posibles de validar datos de entrada usando
una estructura de repetición Repetir-Hasta Que. Para validar que el código de artículo que ingrese
sea correcto usaremos la misma idea. Si no fuera correcto se pedirá un nuevo ingreso. A los efectos
de permitir que el usuario elija cuando quiere finalizar, le vamos a solicitar que ingrese una “S” o “s”
para seguir y una “N” o “n” si quiere finalizar. Por lo tanto, para esta repetición usaremos una
estructura Mientras-Hacer. Necesitamos una variable para guardar si el usuario desea seguir o no, de
tipo caracter (variable continuar); también debemos conocer cuando finaliza un día (variable undia)
y tendremos otra repetición del tipo Mientras-Hacer. Necesitamos otra variable entera para
almacenar el código del artículo (variable codigo), una variable real para almacenar el monto de
venta de un artículo (variable monto) y cinco variables acumuladoras reales (variables art1, art2,
art3, art4 y art5) para sumar los montos de cada uno de los artículos. El ambiente se define como:
Ambiente del algoritmo:
Objeto
Tipo
Descripción
continuar
Variable
caracter
de
entrada,
de
tipo Contiene la respuesta del usuario para
saber si se continúa con el ingreso.
undia
Variable
caracter
de
entrada,
de
tipo Indica si finaliza un día.
codigo
Variable de entrada, de tipo entero
Contiene el código del artículo.
Monto
Variable de entrada, de tipo real
Contiene el monto ingresado.
Variable auxiliar, de tipo real
Acumulador. Contiene la suma de los
montos del artículo 1.
Variable auxiliar, de tipo real
Acumulador. Contiene la suma de los
montos del artículo 2.
Variable auxiliar, de tipo real
Acumulador. Contiene la suma de los
montos del artículo 3.
Variable auxiliar, de tipo real
Acumulador. Contiene la suma de los
montos del artículo 4.
Variable auxiliar, de tipo real
Acumulador. Contiene la suma de los
montos del artículo 5.
art1
art2
art3
art4
art5
Algoritmo:
Versión 1:
t1.1. Definir las variables undia, continuar como caracter.
t1.2. Definir la variable código como entero.
t1.3. Definir las variables monto, art1, art2, art3, art4 y art5 como reales.
39
t2. Consultar si desea seguir procesando y guardar respuesta en continuar.
t3. Mientras el usuario desee seguir procesando días
t3.1. Inicializar acumuladores.
t3.2. Asignarle a la variable undia una “N” o “n” (significa que NO se finalizó con el día)
t3.3. Mientras no finalice un día
t3.3.1. Mientras no se ingrese un código correcto
t3.3.1.1. Solicitar ingreso del código del artículo.
t3.3.2. Solicitar e ingresar monto de venta.
t3.3.3. Dependiendo del valor del código, acumular en el acumulador correspondiente
sumándole monto.
t3.3.4. Solicitar si finalizó un día.
t3.4. Mostrar las ventas de cada artículo y mostrar la venta total del día ingresado.
t3.5. Solicitar si desea procesar otro día.
Versión 2 (final):
Proceso Ventas
//t1.1.
Definir undia, continuar Como Caracter;
//t1.2.
Definir codigo Como Entero;
//t1.3.
Definir monto, art1, art2, art3, art4, art5 Como Real;
//t2. Procesamiento de días
Escribir “Desea procesar otro día” ;
Leer continuar;
//t3.
Mientras continuar = “S” | continuar = “s” Hacer
// Procesamiento de un día
//t3.1.
art1 <- 0;
art2 <- 0;
art3 <- 0;
art4 <- 0;
art5 <- 0;
//t3.2.
undia <- “n”;
//t3.3.
Mientras undia = “N” | undia = “n” Hacer
// t3.3.1. Validación de código
Repetir
Escribir “Ingrese código de artículo”;
40
Leer codigo;
Hasta Que codigo >= 1 & codigo <= 5
// t3.3.2.
Escribir “Ingrese monto de venta”;
Leer monto;
// t3.3.3.
Segun codigo Hacer
1: art1 <- art1 + monto;
2: art2 <- art2 + monto;
3: art3 <- art3 + monto;
4: art4 <- art4 + monto;
5: art5 <- art5 + monto;
FinSegun
//t3.3.4.
Escribir “Finalizó las compras de un día?”;
Leer undia;
FinMientras //del procesamiento de un día
//t3.4.
Escribir “Total de ventas de artículo 1 ”, art1;
Escribir “Total de ventas de artículo 2 ”, art2;
Escribir “Total de ventas de artículo 3 ”, art3;
Escribir “Total de ventas de artículo 4 ”, art4;
Escribir “Total de ventas de artículo 5 ”, art5;
Escribir “Total de ventas del día: ”, art1 +art2 + art3 + art4 + art5;
//t3.5.
Escribir “Desea procesar otro día?”;
Leer continuar;
FinMientras // termina el procesamiento de los días
FinProceso
Construir la tabla de ejecución del algoritmo Ventas con los siguientes datos de entrada: s 1 100 n -1
2 150 n 3 500 s S 5 300 n 4 250 s N
41