Algoritmica y programación

Anuncio
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Antes de incorporar conceptos de programación, debemos hacer hincapié en la importancia
que tiene el desarrollo de la imaginación, para ser capaces de idear la sucesión de hechos que se dan en
un proceso.
Por ejemplo: Imaginemos el procedimiento para cambiar una cubierta de un vehículo: ¿Qué
sucesos involucra?
1º Saber qué cubierta está pinchada.
2º Abrir el baúl.
3º Si tengo cubierta de auxilio, sacarla; en caso contrario pedir ayuda.
4º Verificar el estado del auxilio. Si está en condiciones:
4.1. Buscar, hasta encontrar, las herramientas necesarias para cambiar la cubierta.
4.2. Asegurarse de que el vehículo no se desplace.
4.3. Aflojar los bulones.
4.4. Colocar el criquet en el lugar que corresponda.
4.5. Elevar el vehículo.
4.6. Extraer bulones y cubierta.
4.7. Colocar la cubierta en condiciones y ajustar los bulones.
4.8. Bajar el vehículo.
4.9. Asegurar los bulones.
4.10. Retirar los tacos/piedras puestos para fijar el vehículo.
4.11. Guardar cubierta pinchada, herramientas, y eventuales tacos.
4.12. Fin.
5º En caso de que la cubierta de auxilio no esté en condiciones, deberá llevarse a reparar, para luego efectuar el paso 4.
Esto que acabamos de describir puede llamarse “algoritmo para cambiar una cubierta pinchada”. Así podemos definir:
.
Algoritmo: manera formal y sistemática de representar la descripción de un proceso. Secuencia ordenada de pasos - sin ambigüedades -, repetible, que es solución de
un determinado problema
Las características fundamentales que debe cumplir todo algoritmo son:
a) Debe ser preciso e indicar el orden de realización de cada paso
b) Debe estar definido (si se repite n veces los pasos se debe obtener siempre el mismo resultado)
c) Debe ser finito (debe tener un número finito de pasos)
d) Es independiente del lenguaje de programación que se utilice
La definición de un algoritmo debe describir tres parte Entrada, Proceso, Salida.
1º
2º
3º
4º
5º
6º
7º
8º
9º
10º
11º
12º
Desarrollemos ahora el algoritmo para preparar una ensalada de frutas:
Disponer los ingredientes: azúcar, frutas (manzana, banana, ananá, naranja, cereza, uva, durazno).
Disponer los utensilios: cuchillo, tablita, ensaladera profunda, exprimidor y jarrita.
Lavar meticulosamente toda la fruta.
Seleccionar 4 naranjas, cortarlas por la mitad, exprimirlas y guardar el jugo en la jarrita.
Tomar una fruta.
Si es naranja, manzana o durazno, cortarla en cuartos y pelarla con el cuchillo.
Si es banana, pelarla con la mano.
Si es ananá, corlarla en rodajas, y apoyando cada una en la tablita, quitar con el cuchillo la cáscara.
Tomar cada racimo de uvas, y separarlas, colocándolas en la ensaladera.
Quitar los cabos a las cerezas y colocarlas en la ensaladera.
Cortar las frutas peladas en cubos y colocarlos en la ensaladera.
Rociar el azúcar en forma de lluvia sobre la fruta que está en la ensaladera.
APUNTES TEÓRICOS
-1-
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
13º Agregar el jugo exprimido.
14º Revolver cuidadosamente para que no se deshaga la banana.
15º Fin. (Disfrute su ensalada).
Podrá apreciarse que en este algoritmo los términos son precisos y a veces redundantes, a fin
de cumplir con una especificación formal de los pasos.
Obviamente, el desarrollo de nuestros contenidos estará orientado a problemas no domésticos,
por lo que estos ejemplos persiguen un fin ilustrativo. Nuestro objetivo final será la construcción de algoritmos que funcionen y hagan aquello para lo que fueron desarrollados.
Usted habrá escuchado hablar de programas de computadora; ¿Qué relación tienen éstos con
los algoritmos que acabamos de definir?
Un programa es la suma del/de los algoritmo/s y las especificaciones necesarias para que éste
emita un resultado. En términos formales:
Programa = estructuras de datos + estructuras de control
Fases para la construcción de un programa
0. Entender el problema (esto implica hacer un mapa mental del problema y abarcarlo como un todo).
1. Análisis del problema (esta etapa implica armar el modelo del problema y abstraerlo en sus distintas
estructuras).
2. Programar el modelo de solución propuesto (en pseudocódigo).
3. Codificarlo en un lenguaje de computadora.
4. Cargarlo en la computadora para su ejecución y ajuste.
5. Darle mantenimiento a lo largo de su vida útil.
Las fases 0 y 1 equivalen al trabajo de diseño que realiza un arquitecto. Luego de conversar
con su cliente sobre el objetivo de la edificación a construir, indaga sobre las características globales de
esta última (ubicación geográfica, cantidad de pisos, presupuesto disponible, materiales, superficie cubierta,
etc.) y a partir de ello construye la maqueta que presenta al cliente, y amplía el nivel de detalles para la confección de los planos (fase 2).
Las fases 3, 4 y 5 equivalen a la construcción de la vivienda, con los mismos pormenores que
en la construcción de un programa. A medida que lo vamos haciendo, el cliente propone nuevos detalles
que alteran el ritmo de la programación, con la diferencia que es mucho más fácil rehacer software, que tirar
una pared y levantar otra en otra parte (por ejemplo). Si se trata de software de calidad, los cambios son
mucho más fáciles de realizar.
Inicialmente utilizaremos pseudocódigo para programar. Este lenguaje se utiliza para escribir
algoritmos que luego serán codificados para su ejecución en computadoras. Veremos algunas convenciones que deberán respetarse, para evitar ambigüedades en el desarrollo de los mismos.
También utilizaremos metapalabras, que son palabras que representan un objetivo específico,
por lo que además de restringir su uso a dicho objetivo, deberán ir subrayadas. Las metapalabras que utilizaremos son las siguientes:
hacer
cadena
entonces
escribir
escribirln
no
procedimiento
registro
repetir
termina
tipos
abrir
lógico
sino
leer
programa
y
variables
archivo
hasta
opción
entero
cerrar
arreglo
mientras
si
función
ó
constantes
fin
comienza
de
real
El objetivo de cada una de ellas va anexo a este apunte.
APUNTES TEÓRICOS
-2-
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Como habrá podido observar, la ecuación de la programación estructurada cuenta con Estructuras de Datos, y Estructuras de Control. Comenzaremos nuestro estudio con las primeras mencionadas:
Estructuras de Datos
Los datos que maneja un programa pertenecen a un tipo determinado. Este tipo tiene asociado un conjunto de operaciones posibles (lo que podríamos llamar su álgebra). Nosotros manejaremos tipos
simples estándares, y algunos de los tipos compuestos ó estructurados.
Simple
Estructurado
entero
real
lógico
carácter
cadena
arreglo multi-dimensional
registro
archivo secuencial
arreglo uni-dimensional
En esta primera etapa de estudio utilizaremos los tipos simples, y la cadena como un conjunto
de caracteres. Más adelante desarrollaremos los contenidos de los tipos estructurados.
Entero: tipo que se utiliza para representar valores enteros,
Ejemplos:
18
30
1997
(una edad)
(días en el mes)
(año en curso)
Real: tipo que se utiliza para representar valores del conjunto de números reales.
Ejemplos:
37.18
3.14159
9.8
(una cuota en pesos)
(pi)
(aceleración de la gravedad)
Lógico: tipo que se utiliza para representar valores booleanos(verdadero, falso).
Ejemplos:
verdadero
falso
(estoy estudiando programación)
(estoy descansando en el Caribe)
Carácter: tipo que se utiliza para representar los distintos caracteres empleados tanto para
expresiones aritmético-lógicas como para graficación.
Se escribe entre apóstrofes.
Ejemplos:
'S'
(ese mayúscula)
'∗'
(asterisco)
'#'
(numeral)
'&'
(ampersand)
Cadena: tipo utilizado para expresar palabras.
APUNTES TEÓRICOS
-3-
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Debe ir encerrada entre apóstrofes.
Ejemplos:
'la luna es blanca'
'Lógica y Programación'
'N'
Ahora bien, un programa tiene sentido si desarrolla un algoritmo para más de un dato. De allí
surge la necesidad de representar los datos mediante variables.
Variable: elemento fundamental que representa a los datos a ser procesados mediante un
algoritmo.
Su contenido es variable en el tiempo. Desde el punto de vista de las computadoras, son direcciones de memoria en las que se almacenan los datos que procesa un programa. A cada variable le corresponde su tipo; puede haber más de una variable de un mismo tipo, pero a cada variable le corresponde un
único tipo.
Identificador: nombre único asociado a cada variable.
Ejemplos:
identificador
tipo
edad
estudié
cuota
apellido_y_nombre
ángulo
respuesta
días_en_el_mes
letra
titulo
entero
lógico
real
cadena
real
carácter
entero
carácter
cadena
Estructuras de Control
Son construcciones lógicas que dirigen el flujo de acciones que efectuará el procesador sobre
los datos que maneja un programa, los que estarán organizados en estructuras de datos.
Existen tres estructuras básicas de control, que a su vez pueden combinarse entre sí para formar estructuras más complejas. Ellas son: secuenciación, selección e iteración.
Al hablar de estructuras de control se hace necesario definir qué es un enunciado y qué una
condición.
Enunciado: sentencia o instrucción que representa una operación elemental sobre ninguna,
una o más variables.
Según el número de acciones que se realizan sobre ésta/s, los enunciados se clasifican en nulo(ninguna acción), simple (una sola acción), ó compuesto (más de una).
El enunciado nulo tiene un uso particular que veremos oportunamente.
La operación de
asignación es un enunciado simple, que se representa mediante el signo ←. El formato de dicho enunciado
es:
id_variable "←" expresión.
Esto significa que el valor de la expresión se "almacena" en la variable identificada por el
"id_variable"
Ejemplos:
mes← 'agosto'
año ← 1997
APUNTES TEÓRICOS
-4-
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
pi ← 3.14159
entendí ← verdadero
Ejemplos:
escribir x
leer x
abrir archi
cerrar archi
x ← x+2
Estos son enunciados
simples
Vimos que un enunciado es compuesto si implica más de una operación sobre una o más variables. Al tratarse de un enunciado, debemos agrupar dichas acciones para su tratamiento como único.
Esto se logra encerrando las mismas entre paréntesis. Las metapalabras utilizadas para este fin son comienza y termina.
Ejemplos
•
•
comienza
leer x
y←x+3
escribir x, y
y ← y ∗ 4 + 89 / x
escribir y
escribir 'se terminó'
termina
comienza
escribir '¿Cuál es tu nombre?'
leer nombre
escribir nombre, ' , ¿Cuántos años tenés?'
leer edad
termina
Condición: expresión lógica, la que por su condición de tal, podrá tomar los valores verdadero o falso;
Ejemplos:
x<7
a=b
(a>b) ∧ (x<7)
no fin(archi)
Veamos entonces cada una de las estructuras de control, con ejemplos de aplicación, simbolizando con e los enunciados y con c las condiciones.
secuenciación: sucesión de enunciados que se ejecutan uno a continuación del otro.
e0
e1
e2
...
en
Ejemplos:
•
leer x
x ← x+2
escribir x
•
x←0
Observación: un único enunciado
ya es una secuenciación
APUNTES TEÓRICOS
-5-
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Selección: sentencia que evalúa una expresión, y en función de los valores de ésta, dirige
el flujo del proceso.
Según el tipo de la expresión, como del número de valores posibles que pueda tener, se definen dos
formas de selección:
Selección dicotómica: enunciado formado por una expresión booleana, (verdadera ó falsa)
y dos alternativas disjuntas de flujo de control.
Simbólicamente:
si
c
entonces
sino
e1
e2
lo cual se entiende así: en el flujo de control, se evalúa el valor de certeza de c. Si es cierto, ejecuta e1 y
continúa con el flujo del programa. Si c es falso, ejecuta e2 y continúa con el flujo del programa
Ejemplos:
si x>0
entonces escribir x, ‘positivo’
sino
escribir x, ‘nulo ó negativo’
si fin (archi)
entonces parar←verdadero
parar← falso
sino
Selección Múltiple: enunciado formado por una expresión entera, cuyo resultado pertenece
a un conjunto de opciones, y según el cual se ejecuta uno sólo de los
enunciados alternativos.
Simbólicamente:
opción valor de
valor1: e1
valor2: e2
valor3: e3
..............
valorn: en
termina opción
Ejemplos:
• opción
'I'
'V'
'X'
'L'
'C '
'D'
'M'
romano de
: número ← 1
: número ← 5
: número ←10
: número ← 50
: número ←100
: número ←500
: número ←1000
termina opción
• opción mes de
enero, marzo, mayo, julio, agosto, octubre, diciembre : días ← 31
febrero : días ← 28
abril, junio, setiembre, noviembre : días ←30
termina opción
APUNTES TEÓRICOS
-6-
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Iteración: construcción que indica la repetición de un grupo de enunciados de
acuerdo al
valor de determinada condición.
Según el orden de ejecución del enunciado, como así también del número prefijado o no de repeticiones, veremos que existen tres formas de iteración:
1. ITERACIÓN MIENTRAS
mientras c hacer e
El enunciado e se ejecuta mientras la condición c sea verdadera. Dicha condición
es evaluada antes de ejecutar por primera vez el enunciado. Si el valor lógico de la condición es falso inicialmente, dicho enunciado no se ejecutará.
Ejemplo 1:
En este caso, si el valor que se lee de x es mayor que 5, lo decrementa
leer x
en dos, tantas veces mientras el valor obtenido sea mayor que 5. En
mientras x>5 hacer x←x-2
cambio, si es 5 o menos, no se ejecuta el mientras
Ejemplo 2:
total ← 0
cantidad ← 0
En este caso, se repite la lectura de unidamientras (total ≤ 1235) ν (cantidad < 15) hacer
des, se las cuenta y acumula mientras la
comienza
suma sea menor o igual a 1235 o se hayan
leer unidades
contado 15. Cuando alguna de las dos concantidad ← cantidad + 1
diciones es falsa, imprime el total y la cantitotal ← total + unidades
dad
termina
escribir total , cantidad
Ejemplo 3:
leer x
mientras x < 8 hacer x
Este mientras nunca va a terminar si el primer
valor que ingresa es menor que 8. ¿por qué?
x-3
2. ITERACIÓN REPETIR
repetir e hasta c
El enunciado e se ejecuta hasta que la condición c sea verdadera. Una vez que la condición es
verdadera, termina la iteración. Cabe aclarar que la evaluación de la condición se realiza después de haber
ejecutado el enunciado, lo que permite la ejecución de éste último al menos una vez.
Ejemplo 1:
Traza
leer x
Tiempo
X
repetir
T1
8
x←x/2
T2
4
hasta x<2
T3
2
T4
1
Ejemplo 2 :
sum_altura ← 0
sum_edad ← 0
sum_talle ← 0
canti_per ← 0
repetir
leer nombre, edad, talle, altura
canti_per ←canti_per +1
sum_altura ← sum_altura + altura
sum_edad ← sum_edad + edad
sum_talle ← sum_talle + talle
hasta canti_per = 80
Este segmento lee nombre, edad, talle y altura de
80 personas
APUNTES TEÓRICOS
-7-
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
3. ITERACIÓN PARA
para valor ← limite_inf hasta limite_sup hacer e
donde valor es una variable de tipo entero , cuyo contenido varía desde límite_inf hasta límite_sup, incrementándose en uno para cada ejecución de e . Así, la primera vez se ejecuta tomando el valor limite_inf ,
luego limite_inf +1 (si esto es menor o igual a limite_sup), y así sucesivamente hasta tomar el valor limite_sup.
Ejemplo1:
Para j ← 1 hasta 8 hacer
escribir j + 3
La salida será:
4, 5, 6, 7, 8, 9, 10, 11
Ejemplo 2:
Para k ← 3 hasta 15 hacer
comienza
línea ← k
columna ← k + 10
leer carácter
escribir línea, columna, carácter
termina
Atención: Si observamos los distintos ejemplos anteriores, veremos que cada ciclo se ejecuta en forma
finita, es decir, que a partir de cierta condición, el bucle finaliza. A esto se le dice "satisfecho el ciclo". En
el caso del mientras, ocurre cuando la condición se hace falsa. En el caso del repetir hasta, ocurre
cuando la condición se hace verdadera. Para ello debe haber una sentencia que modifique correctamente el
valor lógico de la condición. Si esto no ocurre, estamos en presencia de un ciclo infinito. Al construir una
estructura iterativa de estos tipos, debemos poner especial cuidado en que el bucle finalice,
Ejemplo:
x←3
mientras x<5 hacer escribir x
nunca estará "satisfecho", porque x nunca dejará de ser menor que 5, es decir, el valor lógico de la condición es siempre verdadero. El resultado de su ejecución será escribir x infinitamente.
Veamos otro caso:
dato ← 3
repetir
dato ← dato + 5
suma ← suma + 12
escribir dato, suma
hasta
dato < 7
Este "ciclo" es infinito pues dato se incrementa en cinco (partiendo del valor 3), por lo que dato < 7 nunca
será verdadero. Estos errores son muy severos en la programación, y para resolverlos, se debe “apagar” la
computadora.
Ya estamos en condiciones de escribir un algoritmo:
•
Dados tres números enteros positivos, leídos en forma ascendente, desarrollar el algoritmo
que determine:
⇒ si forman triángulo
⇒ si es equilátero, isósceles o escaleno
⇒ el área del mismo
Recordemos las distintas fases para la construcción de un algoritmo: debemos primero entender el problema.
¿Qué características tiene el ingreso de los datos? ¿Ordenados, enteros, etc.?
APUNTES TEÓRICOS
-8-
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
¿Qué condición deben cumplir los datos para formar un triángulo?
¿Cuándo es equilátero, isósceles, escaleno?
¿Cuál es la fórmula de su superficie?
Una vez resueltos esos interrogantes, nos ponemos a escribir el algoritmo.
comienza
{ comienza el algoritmo }
leer lado1, lado2, lado3
dato_válido ← (lado1< lado2 ) Λ (lado2 < lado3)
{aquí debo controlar que ingresen en orden ascendente. si no cumplen esa condición, pido otros datos, y así
repetidamente hasta que la cumplan, por lo tanto, debo utilizar un ciclo}
mientras ∼ dato_válido hacer
comienza
escribir 'sus datos no ingresaron en forma ascendente. Ingrese una nueva terna'
leer lado1, lado2, lado3
dato_valido ← (lado1< lado2) Λ (lado2 < lado3)
termina
{ ya tengo seguridad de que los datos son correctos. Esto pasa a ser la pre-condición para el algoritmo}
{ ahora controlo si forman triángulo. En caso afirmativo, determino su tipo}
triángulo ← (lado1< lado2 + lado3) Λ(lado2 < lado1 + lado3) Λ (lado3 < lado1 + lado2)
si no triángulo
entonces escribir 'sus datos no determinan un triángulo'
sino
comienza
si (lado1 = lado2) Λ (lado2 = lado3 )
entonces mensaje ← 'equilátero'
sino
si (lado1 = lado2) ν (lado2 = lado3)
entonces mensaje ← 'isósceles '
mensaje ←'escaleno'
sino
escribir 'sus datos determinan un triángulo', mensaje
2
 lado1 

lado2² − 
 2 
 lado1 * alt u ra 

superficie ← 


2
escribir 'El área de su triángulo es', superficie
termina
altura ←
termina
{finaliza el algoritmo}
Nótese el detalle de los comentarios. Estos deben ir encerrados entre llaves { } , y se utilizan para clarificar
la acción de cada enunciado.
Regla fundamental de la composición de estructuras:
Es posible combinar las estructuras de control de secuenciación, selección e iteración utilizando para tal fin,
las mismas estructuras.
APUNTES TEÓRICOS
-9-
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Ejemplo1:
e0
e1
si c1 entonces mientras c2 hacer
comienza
e2
e3
e4
termina
sino e5
e6
Ejemplo 2:
e0
mientras c1 hacer
comienza
si c2 entonces comienza
e1
e2
e3
termina
sino e4
e5
Ejemplo 3
• El siguiente algoritmo calcula e imprime el total de lluvia caída (de más de 5 mm³) y la tempe-
ratura promedio de aquellas menores que 35°C.
total_lluvia ← 0
total_temp ← 0
canti_est ←0
leer estación, lluvia, temperatura
mientras estación ≠ 0 hacer
comienza
canti_est ← canti_est + 1
si lluvia < 5 entonces escribir 'no me interesa'
sino total_lluvia ←total_lluvia + lluvia
si temperatura > 35 entonces escribir '¡¡qué calor!!'
sino total_temp ← total_temp + temperatura
leer estación, lluvia, temperatura
termina
escribir 'la lluvia caída en el año es', total_lluvia
escribir 'el promedio de temperaturas es', total_temp / canti_est
¿ Cuándo termina el ingreso de datos?
El criterio para finalizar el ingreso de datos lo establece el programador, en función del modelo que esté
programando. Habrá casos en los que un valor determinado define la finalización de un proceso (por ejemplo el día 365 de un año), o el carácter <N> en una respuesta a la pregunta de ‘¿desea ingresar más datos?’, o un cero ingresado como denominador de una división. En fin, las situaciones son muy particulares
como para establecer un criterio general. Podrá observarse en cada caso la forma de resolverlo.
Ejemplo
•
Ingresan datos hasta que la suma de los mismos sea mayor que 12345.
suma ← 0
repetir
leer dato
suma ← suma + dato
hasta suma > 12345
• Suma datos mientras el operador lo desee.
suma ← 0
escribir '¿Desea ingresar datos? Pulse <S> ó <N>'
leer respuesta
mientras respuesta = 'S' hacer
comienza
leer dato
APUNTES TEÓRICOS
- 10 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
suma ← suma + dato
escribir '¿Desea ingresar más datos? Pulse <S> ó <N>'
leer respuesta
termina
escribir 'la suma de sus datos es', suma
•
Calcula cocientes de datos mientras el denominador sea distinto de 0.
leer numerador
leer denominador
mientras denominador ≠ 0 hacer
comienza
n u merador
den omin ador
escribir 'El resultado de la división es ',cociente
leer numerador
leer denominador
termina
cociente ←
•
Calcula la productoria de los N primeros números naturales.
leer N
{N>0}
Productoria ← 1
Cantidad ← 1
mientras Cantidad ≤ N hacer
comienza
Productoria ← Productoria ∗ Cantidad
Cantidad ← Cantidad + 1
termina
escribir ' el producto de los primeros', N , 'números naturales es', Productoria
Variables de uso particular
Usted habrá observado que en los distintos algoritmos de la suma, como en el de la Productoria utilizamos variables que "acumulan" valores, como así también utilizamos otras que "cuentan". Estas
variables se denominan Acumulador y Contador respectivamente. Sus nombres conceptuales indican
la función que cumplen en un algoritmo. Obviamente estas deberán inicializarse en el momento oportuno.
Hay otra variable que tiene un comportamiento particular, y se utiliza con mucha frecuencia en
todo tipo de algoritmo. Se trata de la "marca", también conocida como "llave", "flag", "bandera", "switch" o
cualquier término que signifique indicador.
Marca: variable cuyos valores son indicadores de situaciones particulares
Ejemplos:
•
El siguiente algoritmo lee un día y la presión correspondiente y determina el día en que se
registró la mínima presión, imprimiendo ambos resultados.
marca ← verdadero
mientras haya datos hacer
comienza
leer día, presión
si marca entonces
comienza
dia_min ← día
mínimo ← presión
APUNTES TEÓRICOS
- 11 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
marca ← falso
termina
sino si presión < mínimo entonces
comienza
dia_min ← día
mínimo ← presión
termina
termina
escribir 'El día ',dia_min, ' se registró la mínima presión de ',mínimo,' hectopascales.'
En este caso la marca toma el valor verdadero para el primer par de datos que se necesita
como punto de comparación.
APUNTES TEÓRICOS
- 12 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
•
El siguiente algoritmo lee un número y determina si es primo o no
divisor ← 2
primo ← verdadero
leer numero
mientras primo ∧ (divisor <
n u mero ) hacer
Dejamos al lector el análisis
del objetivo de la marca primo.
 n u mero 
si 
* divisor = numero entonces primo ← falso
 divisor 
sino divisor ← divisor + 1
escribir numero
si primo entonces 'es primo'
sino 'no es primo'
Consistencia
En todos los procesos es imprescindible que la información que ingresa sea consistente, es
decir válida con respecto al dato que representa; corresponde al programa de ingreso de datos dicha verificación.
Consistencia: proceso de verificación de la validez de la información que ingresa.
•
Calcula el factorial de un número entero positivo.
leer número
{ a continuación consistimos el valor de numero, que debe ser mayor o igual que cero}
mientras número < 0 hacer
comienza
escribir 'Dato no válido'
escribir 'Ingrese otro número'
leer número
termina
{ número es mayor o igual que cero }{precondición para el factorial}
factorial ← 1
genera ← 1
mientras genera ≤ número hacer
comienza
factorial ← factorial ∗
genera
genera ← genera + 1
termina
escribir 'el factorial de ' , número, 'es', factorial
{ factorial contiene el factorial de número} { postcondición del factorial }
•
Ingresa nº_alumno, edad, peso, estatura. Finaliza cuando nº_alumno es cero.
leer nº_alumno, edad, peso , estatura
mientras nº_alumno ≠ 0 hacer
comienza
{ controla la edad}
mientras (edad < 17 ) ∨ (edad > 110) hacer
APUNTES TEÓRICOS
- 13 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
comienza
escribir 'Dato no válido'
escribir 'Ingrese otra edad'
leer edad
termina
{ controla el peso}
mientras (peso < 30 ) ∨ (peso > 100) hacer
comienza
escribir 'Dato no válido'
escribir 'Ingrese otro peso'
leer peso
termina
{ controla la estatura}
mientras (estatura < 1,40 ) ∨ (estatura > 2,10) hacer
comienza
escribir 'Dato no válido'
escribir 'Ingrese otra estatura'
leer estatura
termina
escribir nº_alumno, edad, peso , estatura
leer nº_alumno, edad, peso , estatura
termina
Estructura General de un Programa
Hasta el momento hemos trabajado con los algoritmos, sin dar ninguna especificación acerca de las
variables que intervienen en él. Dentro de las premisas a respetar en la programación estructurada, está la
de presentar las definiciones y/o declaraciones según un orden preestablecido. A saber:
Programa <nombre>
Constantes
{ lista de constantes que utilizaremos en el programa}
Tipos
{lista de tipos no estándares que utilizaremos en el programa}
Variables
{ lista de variables, con su tipo, que utilizaremos en el programa}
Procedimientos y/o Funciones
{módulos que utilizaremos en el programa}
comienza {el programa principal}
{ lista de enunciados del programa}
termina { el programa principal }
Donde:
<nombre> es el identificador del programa
{ lista de constantes que utilizaremos en el programa} es la lista de identificadores cuyo contenido no
se modifica el la ejecución del programa;
Ejemplos:
pi=3.14159
mi_nombre='patricia'
mi_fecha_nac='30/02/21'
días_año_98= 365
APUNTES TEÓRICOS
- 14 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
{ lista de tipos que utilizaremos en el programa} es la lista de tipos que define cada programador según sus necesidades.
Ejemplos:
par = (0,1)
días_semana=(lun, mar, mier, jue, vie, sab, dom)
útiles =(lápiz, goma, cuaderno, regla, birome)
natural=1.maximo_entero
negativo = -maximo_entero..-1
{ lista de variables que utilizaremos en el programa} es la lista de los identificadores de las variables
globales del programa.
Variable global: aquella cuyo alcance de utilización es tanto el programa principal, como
los módulos contenidos en él.
módulos contenidos en el programa son las unidades en las que dividimos el problema, y que
luego del ejemplo veremos detalladamente.
El siguiente programa lee e imprime el número combinatorio de "m" elementos tomados de a "n", finalizando el ingreso de datos cuando m = n, y ambos sean cero. El rango de valores que pueden tomar es
de cero a cincuenta.
Ejemplo
Programa combinatorio
Constantes
Cátedra = 'Lógica y Programación'
Año_curso='1997'
Tipos
intervalo = 0..50
Variables
válido : lógico
m , n: intervalo
m_aux, n_aux, mn_aux : intervalo
m_fac, n_fac, mn_fac : real
mn_dif : intervalo
combi : real
comienza {programa Principal}
repetir
valido ← falso
leer m, n
{ hago consistencia de los datos }
mientras no válido hacer
si (m < n) ∨ (m < 0) ∨ (n < 0) entonces leer m,n
sino válido ← verdadero
{ los datos son válidos }
{ calculo el factorial de m }
m_aux←1
m_fac ← 1
mientras m_aux ≤ m hacer
comienza
m_fac←m_fac ∗ m_aux
m_aux ← m_aux + 1
termina
{ calculo el factorial de n }
APUNTES TEÓRICOS
- 15 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
n_aux←1
n_fac ← 1
mientras n_aux ≤ m hacer
comienza
n_fac←n_fac ∗ n_aux
n_aux ← n_aux + 1
termina
{ calculo el factorial de m-n }
mn_dif ← m - n
mn_aux←1
mn_fac ← 1
mientras mn_aux ≤ mn_dif hacer
comienza
mn_fac←mn_fac ∗ mn_aux
mn_aux ← mn_aux + 1
{ calculo el número combinatorio e imprimo el resultado }
combi← m_fac/n_fac/mn_fac
escribir 'la combinación de ', m, 'tomados de a ', n, 'es ', combi
hasta (m=n) ∧ (m=0)
termina {programa Principal}
Obsérvese que, dentro del programa, ha sido necesario repetir en tres oportunidades el segmento de código
utilizado para calcular el factorial de un número: n!, m! y (m-n)!. Esto puede simplificarse re-escribiendo el
programa de la siguiente forma:
Programa combinatorio
Constantes
Cátedra='Lógica y Programación'
Año_curso='1997’
Tipos
intervalo=0..50
Variables
m,n:intervalo
m_fac, n_fac, mn_fac : real
mn_dif : intervalo
combi : real
funcion factorial (numero: entero): entero
Variables
num_aux : intervalo
num_fac: real
{ número ≥ 0 }
comienza
num_aux ←1
num_fac ← 1
mientras num_aux ≤ numero hacer
comienza
num_fac ← num_fac ∗ num_aux
num_aux ← num_aux + 1
termina
factorial ← num_fac { asigno el resultado a la función } { factorial contiene el factorial de numero }
termina { fin funcion factorial }
procedimiento leo_controlo(ref m, n: intervalo)
Variables
valido: lógico
APUNTES TEÓRICOS
- 16 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
comienza
valido ← falso
leer m, n
{ hago consistencia de los datos }
mientras no válido hacer
si (m < n) ∨ (m < 0) ∨ (n < 0) entonces leer m,n
sino válido ← verdadero
termina { fin procedimiento leer_valores } { m y n son válidos }
comienza {programa Principal}
repetir
leo_y_controlo(m,n)
m_fac ← factorial(m)
n_fac ← factorial(n)
mn_dif ← m - n
mn_fac ← factorial(mn_dif)
{ calculo el número combinatorio e imprimo el resultado }
combi ← m_fac/n_fac/mn_fac
escribir 'la combinación de ', m, 'tomados de a ', n, 'es ', combi
hasta (m=n) ∧ (m=0)
termina {programa Principal}
Como puede observarse, en este último ejemplo hemos resuelto la repetición de código que se presentaba en el ejemplo anterior mediante el uso de una función que calcula el factorial de un número. Bastó
con definir sólo una vez la función, y luego invocarla las veces necesarias con los diferentes argumentos de
los cuales se quería conocer el factorial.
También podrá observarse el uso de un procedimiento para leer y controlar la información. Ese control es la consistencia de la misma.
Teniendo en cuenta este comportamiento, podemos definir:
función: bloque de instrucciones cuyo objetivo es devolver al módulo que la invoca, un valor de un tipo predefinido.
La función genera una dirección de memoria asociada a su identificador, y el valor que ésta produce,
se almacena en esa dirección.
procedimiento: bloque de instrucciones al que se invoca para producir un valor, más de
uno o ninguno. Estos valores son referenciados por el módulo llamador.
Un procedimiento o una función puede ser llamado desde el programa principal o desde otro
procedimiento o función.
Una de las diferencias conceptuales entre función y procedimiento está dada por su forma de
invocación: Una función puede invocarse indistintamente desde una Incorrecto
sentencia de impresión, de asignación
y desde un condicional, teniendo en cuenta que nunca puede invocarse en forma directa.
• factorial(n)
En nuestro ejemplo:
Correcto
• leer factorial(n)
• n_fac ← factorial(n)
• mientras factorial(numero) > 1 hacer ...
Un procedimiento, por otro lado, debe invocarse en forma directa, es decir, mediante una sentencia de
procedimiento, la que consta del nombre del mismo y de los parámetros actuales.
Ejemplo:
Correcto
Incorrecto
leer_valores(n,m)
x ← leer_valores(n,m)
APUNTES TEÓRICOS
- 17 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Veremos que la interacción entre los módulos se realiza a través de argumentos ó parámetros,
los que contienen ó referencian las direcciones de los valores de comunicación entre los módulos. En la
sentencia de invocación están los parámetros actuales, los cuales se corresponden con una dirección de
memoria. En el encabezamiento de función o procedimiento están los parámetros formales. A su vez,
estos pueden ser parámetros valor y por referencia.
Parámetro formal: identificador con tipo, en función del cual se define el procedimiento ó
función
Ejemplo
En la función factorial, <número> es el parámetro formal.
En leo_y_controlo, los parámetros formales son <m> y <n>
Los parámetros formales son los utilizados en la declaración del procedimiento, y son llamados también
ficticios, porque no tienen posiciones de memoria asignadas sino hasta la invocación del procedimiento.
Parámetro actual: identificador de variable utilizado en la invocación del procedimiento ó
función, siendo dicha variable global al módulo que se llama.
Ejemplo
Al llamar a factorial cada vez, lo hacemos usando una variable global: m, n, mn_dif ; las tres
son el parámetro actual en cada llamado.
El identificador de los parámetros formales es independiente del identificador de los actuales, por lo tanto,
pueden ser iguales ó distintos. Lo que sí debe respetarse es el orden, número y tipo.
Ejemplo
Sea el siguiente encabezamiento de procedimiento:
⇒ Procedimiento pepe( ref ola:real; ref katre:entero; titulo:cadena)
ola, katre y título son parámetros formales. Ahora bien, supongamos que invoco a pepe de la siguiente manera:
⇒ pepe( dato, valor, encabezamiento).
dato debe ser una variable real.
valor debe ser una variable entera
encabezamiento debe ser una variable cadena.
Bajo estas definiciones, no puedo llamar a pepe así:
⇒ pepe(encabezamiento, dato, valor)
Veamos ahora la diferencia conceptual entre parámetro valor y parámetro por referencia,
parámetro valor : es aquel cuyo contenido no se modifica al ejecutarse el módulo invocado,
ya que éste utiliza una copia del contenido de la dirección de memoria correspondiente.
El parámetro valor actual puede ser una constante.
parámetro por referencia: es aquel cuyo contenido puede inicializarse ó modificarse al ejecutarse el módulo invocado. Esto ocurre pues el módulo trabaja
con la dirección de memoria del parámetro actual correspondiente, y el p. formal hace referencia a esa dirección. El actual
debe ser siempre una variable.
APUNTES TEÓRICOS
- 18 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Otra diferencia entre función y procedimiento está dada por la cantidad de parámetros que devuelven al
módulo llamador: Una función devuelve un único valor contenido en la dirección asociada al identificador de
la función, mientras que un procedimiento puede devolver uno, ninguno o más de un valor. Si fuera el caso
en el que un procedimiento devuelve un valor o más, esto último está contenido en la dirección de los parámetros actuales correspondientes.
Ejemplos:
•
El siguiente procedimiento imprime títulos y totales:
Procedimiento Impresión(Total_ventas:real, Num_Emp,Cant_ventas:entero,
Premio:real)
Variables
bonif:real
{en esta variable calculo la bonificación por las ventas}
comienza
escribir'El total de ventas del empleado ',Num_Emp, 'es ', Total_ventas, '$'
escribir'Las unidades vendidas fueron', Cant_ventas
bonif ← (Total_ventas ∗ Premio)/100
escribir 'Su Premio por ventas realizadas es', bonif ,'$'
termina
Obsérvese que este procedimiento no referencia ninguna dirección al módulo que lo llamó. Todos los
parámetros formales que utiliza son por valor.
La siguiente es una sentencia de procedimiento que llama a Impresión.
{ en el bloque anterior a este llamado, se calculó el total de las ventas y se contaron las unidades de las mismas;
asimismo, se leyó el porcentaje de bonificación que le corresponde}
Impresión(Ventas, Nro_Emp, Unidades, Porcentaje)
•
El siguiente procedimiento lee y controla los coeficientes de un polinomio de tercer grado.
Procedimiento leo_controlo(ref a1,a2,a3,a4:real)
comienza
leer a1,a2,a3,a4
mientras a1 = 0 hacer
comienza
escribir 'dato no válido', 'ingrese a1'
leer a1
termina
termina
Obsérvese que este módulo produce 4(cuatro) valores, y a él no ingresa ningún valor desde el módulo que
lo invocó; es decir, que los parámetros formales que necesita son sólo por referencia. La siguiente es una
sentencia de procedimiento que lo invoca.
leo_controlo(c1 , c2 , c3,, c4)
•
El siguiente procedimiento actualiza la fecha, si ésta es anterior al 31/12/2000.
Procedimiento Actualizo( ref día: día_válido, ref mes:mes_válido, año:año_válido)
{ considero que está definido el tipo día_válido, mes_válido y año_válido y que el procedimiento consistir
controla que los valores que ingresan estén en el rango permitido para día, mes y año}
constantes
año_hoy=2000
Variables
día_hoy: día_válido
mes_hoy: mes_válido
comienza
si año < año_hoy entonces
APUNTES TEÓRICOS
- 19 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
comienza
leer día_hoy, mes_hoy
consistir (día_hoy, mes_hoy)
año ← año_hoy
mes ← mes_hoy
día ← día_hoy
termina
termina
Actualizo (día, mes, año)
En este caso, si al invocar Actualizo los contenidos son:
[día]=15
[mes]=1
[año]=2000, entonces el procedimiento no
produce ningún cambio, y las variables conservan su contenido.
En cambio, si los contenidos son:
[día]=15
[mes]=10
zará los contenidos de las variables, pasando éstas a ser:
[día]=25
[mes]=7
(esto fue impreso el 25/7/2000)
[año]=94, entonces el procedimiento actuali[año]=2000
NÚMEROS ALEATORIOS
En el mundo real, ocurren sucesos determinados, todos los días, como por ejemplo levantarnos, higienizarnos, desayunar, salir de la casa al trabajo, al estudio o a cualquier otro evento previamente conocido. Y
puede ocurrir que esa mañana estemos con fiebre, malestar por algún virus presente en nuestro organismo,
o también puede ocurrir que estemos muy bien y al querer higienizarnos descubramos que no está la pasta
dentífrica, o desapareció el cepillo de dientes, o el peine, o ...... También puede ocurrir que después de levantarnos perfectamente y de higienizarnos sin inconvenientes, al preparar el desayuno descubramos que
cortaron el gas , o que no hay más yerba, o mate, etc. Etc. En síntesis, aún frente a sucesos determinados,
es probable que ocurran otros no previstos. Los primeros corresponden a los sucesos determinísticos, y
los segundos a los sucesos aleatorios. Un suceso es determinístico cuando la probabilidad de que ocurra
es del 100%, es decir que hay certeza de que ocurra. Mientras que un suceso es aleatorio en caso contrario. A estos fenómenos comúnmente se les dice al azar. Veamos a continuación ejemplos de ambos fenómenos.
DETERMINÍSTICO
ALEATORIO
Todos los días tengo hambre
Que me contagie una gripe en una reunión
de amigos, en la que alguien está afectado
Se rompe un plato de porcelana cuando lo
tiro al piso
Pongo un vaso en el borde de la mesada. La
probabilidad de que se rompa es del 50 % (*)
Se rompe un vidrio de una ventana cuando le Cae un plato al piso. La probabilidad de que
tiran una piedra con fuerza
se rompa es de 60 % (**)
Choco al auto que va delante de mí al frenar
y descubrir que los frenos están rotos
La probabilidad de que los frenos estén rotos
es del 10/00
Es mi cumpleaños y lo festejaré con mis
amigos
Hay un 30% de probabilidad de que en mi
cumpleaños tenga que viajar a Bs. As.
APUNTES TEÓRICOS
- 20 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
El segundo parcial es el 4 de noviembre
El 15 de octubre a las 23.30 se desató un
huracán en la Patagonia
(*) Esta probabilidad depende de los movimientos que haya en la cocina, de la edad de los que se movilizan
en ella, y de la torpeza en su desplazamiento. Si en la cocina hay niños, seguramente esa probabilidad aumente, y si hay adolescentes, tal vez se convierta en un suceso determinístico
(**) Esta probabilidad depende de la calidad, la forma y el material del plato.
Ahora bien, qué tiene que ver este concepto con la informática. Ocurre que con frecuencia tendremos que
manejar dicho concepto, ya sea para simular un fenómeno, para acceder aleatoriamente a un elemento,
para generar números aleatorios, etc. Etc. .Como concepto, pertenece a la rama Estadística de la Matemática Aplicada, por lo que en ella lo estudiarán con profundidad.
Generalmente se utilizan recursos azarosos para asignar probabilidades a un suceso, por ejemplo:
• La probabilidad de que salga cara en la moneda es 0.50, y se usa dicho lanzamiento para asignar
probabilidad de esa magnitud.
• La probabilidad de que salga un as en el dado es 1/6, por lo que se usa dicho lanzamiento para asignar
probabilidad de esa magnitud.
• La probabilidad de que salga un caballo de espada es 1/42 (contando los comodines es un mazo común) por lo que se usa dicha extracción para asignar probabilidad de esa magnitud.
Nosotros simplemente definiremos una función matemática que permite generar números aleatorios
uniformemente distribuídos (es decir que tienen la misma probabilidad de salir).
Esta función es recurrente, y se define así:
xi = F(x i-1)
donde x0 es el valor inicial, llamado semilla y x0 ≥ 0
A su vez, se necesitan otros parámetros, cuyo fundamento matemático escapa del dominio de este
desarrollo, y simplemente los definiremos y aplicaremos. Estos son:
a
multiplicador (a ≥ 0)
c
incremento (c ≥ 0)
m
módulo
(m > x0, m > a , m > 0)
La función con la que nosotros trabajaremos para definir una sucesión de números aleatorios es:
x n+1 = ( axn + c ) mod m , donde mod es el operador matemático entero módulo p que definimos en
el Anexo Matemático.
Esta fórmula produce números enteros entre 0 y m.
Supongamos que elegimos arbitrariamente x0 = 3, a = 7, c = 5 y m = 10
La sucesión sería: 3 6 7 4 que se repite cíclicamente.
Nosotros elegiremos el valor m = 2 15 = 32768
c puede ser nulo
a debe ser de un orden de magnitud comparable con m, y también hay una teoría de “mejor elección” que está fuera de nuestro dominio de conocimiento
Así, la fórmula con incremento nulo será:
x n+1 = axn mod m
Para obtener la tabla de números aleatorios uniformemete distribuídos (ri) , se divide xn por m - obteniéndose números reales entre 0 y 1Los lenguajes de programación de alto nivel, tienen incorporada dicha función, denominada RANDOM. Nosotros la definiremos en seudocódigo.
APUNTES TEÓRICOS
- 21 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Cadenas
• DEFINICIÓN
Una cadena es una secuencia finita de caracteres alfanuméricos, el primero de los cuales es
alfabético, y se caracteriza por tener una longitud. La longitud de una cadena es el número de caracteres
que posee.
• DECLARACIÓN DE VARIABLES DE TIPO CADENA
La declaración de variables de tipo cadena se realiza de manera similar a la de otros tipos,
indicando el nombre de la variable, el tipo predefinido (cadena) y la longitud máxima de caracteres que podrá contener.
tipos
palabra: cadena(40)
variables
encabezamiento, titulo: palabra
• OPERACIONES
Existen varias operaciones predefinidas para su uso con cadenas.
Concatenación:
Acción por la que se obtiene una cadena formada por la yuxtaposición de los caracteres de los operandos cadenas. El símbolo operador es el +.
Ejemplo:
texto
‘Juan’ + ‘consulta’ + ‘ dudas’ da como resultado la cadena ‘ Juan consulta dudas’ en la variable
texto.
parrafo
encabezamiento + ‘ ‘ + titulo
da como resultado la cadena ‘Primer Parcial 30/02/2050’
en la variable parrafo, si la variable encabezamiento contiene ’Primer Parcial’ y titulo contiene ’30/02/2050’
Funciones:
LONG(cadena): devuelve la longitud de la cadena.
Ejemplos:
variable
cadena
contenido
sentencia de asignación
pali
‘pepe’
longi
titulo
‘Día del libro’
longi long(titulo)
encabeza ‘Primer Parcial’
long(pali)
resultado:
variable contenido
entera
longi
4
longi
13
canti_letras long(titulo) canti_letras 14
CADENA(número): devuelve una cadena que contiene el número que le fue pasado como parámetro a
la función, pero en formato alfanumérico.
APUNTES TEÓRICOS
- 22 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
variable
tipo
contenido
sentencia de asignación
edad
entero 18
cad_edad
precio
entero 75
cad_precio
densidad
real
cad_densi
12.356
cadena(edad)
cadena(precio)
variable
resultado(tipo
cadena)
cad_edad
‘18’
cad_precio
‘75’
contenido
cadena(densidad) cad_densi
’12.356’
NUMERO(cadena): devuelve el valor numérico de la cadena. Si la cadena contiene caracteres no numéricos, la función devuelve 0.
variable
tipo
contenido
sentencia de asignación
numero(titu1)
variable
resultado
titu1
cadena ‘18’
edad
titu2
cadena ‘75’
precio
titu3
cadena ‘12.356’
densidad numero(titu3) densidad
titu4
cadena ‘resultados’ valor numero(titu4)
numero(titu2)
tipo
contenido
edad
entero 18
precio
entero 75
valor
real
12.356
entero 0
SUBCADENA(cadena,posición,long): devuelve una cadena formada por “long” cantidad de caracteres
tomados de “cadena” a partir de “posición”
variable
contenido
cadena
titu1
‘telecomunicaciones’ pal
Subcadena(titu1,5,14)
variable
resultado
contenido
(tipo cadena)
pal
‘comunicaciones’
titu2
‘empapado’
pal
Subcadena("titu2",3,4)
pal
‘papa’
cad_
num
‘12.356’
p_entera
p_entera
‘12’
cad_
num
‘12.356’
p_decimal
sentencia de asignación
Subcadena(cad_num, 1, 2)
Subcadena(cad_num, 4, 3) p_decimal
‘356’
BUSCAR(cadena_fuente,cadena): devuelve la posición a partir de la cual se encuentra “cadena” dentro de “cadena_fuente”. Si “cadena” no es una subcadena de “cadena_fuente”, la función devuelve el
valor 0.
APUNTES TEÓRICOS
- 23 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
titu1
‘tengo hambre’
posi buscar(titu1,’hambre’)
variable
resultado(tipo
entero)
posi
titu2
‘este ejemplo’
lugar
lugar
6
cad_num
‘12.356’
l_punto
buscar(cad_num, ‘.’)
l_punto
3
l_punto
buscar(cad_precio,’.’)
l_punto
0
variable
cadena
contenido
cad_precio ‘$123,56’
sentencia de asignación
buscar(titu2, ‘ejem’)
contenido
7
Procedimientos:
INSERTAR(cadena, ref cadena_fuente,posición): inserta “cadena” a partir de “posición” en “cadena_fuente”.
Ejemplo:
Insertar(’García’, nombre,6)
si [nombre]=‘José Rodríguez’, esta variable pasa a ser ‘José García Rodríguez’
Insertar(’no ‘, frase ,4,)
si [frase] = ‘Yo soy un estudiante’, luego de Insertar queda [frase]=‘Yo no soy un estudiante’
BORRAR(ref cadena_fuente,posición_ini,cant): borra ‘cant’ cantidad de caracteres de ‘cadena_fuente’ a partir de ‘posición_ini’.
procedure Delete(var S: String; Index: Integer; Count:Integer);
Ejemplo:
Borrar( comic,5,3)
si [comic]= ‘Picapiedra’, después de Borrar queda [comic]= ‘Picadra’
Borrar(título,1,14)
si [título]= ‘Algorítmica y programación’ después de Borrar queda [título]= ‘programación’
Comparación de Cadenas:
Las cadenas pueden compararse haciendo uso de los operadores de comparación y se admiten las siguientes alternativas:
= (igual)
Dos cadenas son iguales cuando cada elemento de ambas cadenas coincide.
nombre = ‘Alberto’ será verdadero cuando nombre esté definido como cadena de siete o más caracteres y
contenga el texto ‘Alberto’
<> (distinto)
APUNTES TEÓRICOS
- 24 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Una cadena es distinta de otra cuando al menos uno de sus caracteres lo es.
‘z’ <> ‘Zeta’ es verdadero, ‘PC’ <> ‘PC ‘ es verdadero (porque posee un espacio), ‘hola’ <> ‘HOLA’ es verdadero, porque las letras mayúsculas son distintas de las minúsculas.
Cuando dos cadenas comiencen igual, el primer carácter distinto es el que decidirá sobre el valor de
certeza de la comparación (por menor o mayor).
< (menor)
Una cadena es menor que otra cuando los caracteres que la componen son
‘menores’ (ordinalmente hablando) que los de la segunda.
‘a’ < ‘b’ es verdadero, ‘Z’ < ‘A’ es falso; ‘programación’ < ‘programar’ es verdadero.
> (mayor)
Una cadena es mayor que otra cuando los caracteres que la componen son
‘mayores’ (ordinalmente hablando) que los de la segunda
‘c’ > ‘b’ es verdadero, ‘F’ > ‘Z’ es falso; ‘programar’ > ‘programador’ es verdadero ‘papel’ < ‘papelon’ es
verdadero
APLICACIÓN A CADENAS DE NÚMEROS: Dígito Verificador
Todos los sistemas de información se basan en el uso de una clave única de acceso a la misma, la cual
debe tener un comportamiento biunívoco, es decir, para determinada información hay una única clave de
acceso a ésta, y esa clave permite acceder sólo a dicha información. Por ejemplo:
⌦ El número del Documento Nacional de Identidad
⌦ El número de cuenta de una Caja de Ahorros
⌦ El número de cuenta de una Cuenta Corriente
⌦ El número de afiliación a una AFJP
⌦ El CUIL
⌦ El CUIT
Y podríamos seguir mencionando cientos de claves que pueden ser por Ud. conocida.
¿ Alguna vez se preguntó qué pasa si se equivoca al escribir uno de los dígitos de cualquiera de esas claves?
¿ y si está en un sistema computarizado, y pulsa una tecla errónea? ¿Qué pasa?. Para ello existe el Dígito
verificador. Éste se integra a la clave, como un último dígito, a continuación de una barra ( / ), y es lo que
permite detectar algún error en el ingreso de los dígitos de la clave. Ud. se preguntará qué pasa si uno se
equivoca en más de un dígito. En estos casos la probabilidad de detección del error es muy alta, y depende
del procedimiento elegido para generar el dígito verificador.
¿ Cómo se integra este dígito a la clave ?
Al darse el alta a cualquier clave del sistema, se aplica el procedimiento a la misma, y se concatena el resultado en la posición n+1 de la clave. A partir de ese momento, sea cual fuere la operación que se realice en
el sistema, el usuario ingresa los n+1 dígitos. El programa calcula el procedimiento con los n dígitos de la
clave, y verifica que coincida el resultado con el n+1 ingresado. En caso afirmativo, acepta la clave ingresada; sino, emite un mensaje.
Veamos a continuación, uno de los tantos algoritmos de obtención del Dígito Verificador.
Sea la siguiente distribución de dígitos, de una clave compuesta por 8:
posición
1
2
3
4
5
6
7
8
clave
1
1
3
7
2
2
0
1
Paso 1
Paso 2
1
+
7
9
+
2
+
1 =11
11
x
3
=33
APUNTES TEÓRICOS
- 25 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Paso 3
1
+
3
+
2
Paso 4
+
0
=6
33
+
6 =39
Paso 5
DV=1
Procedimiento:
La posición de los dígitos que conforman un código pueden ser numerados de izquierda a derecha, de modo que el dígito verificador ocupa el último lugar (n+1). Los pasos para calcular el dígito verificador son los
siguientes:
1. Comenzando desde la posición 2 del número, sume todos los dígitos que se encuentran en posiciones
pares.
2. Multiplique el resultado por 3.
3. Comenzando desde la posición 1 del número, sume las posiciones impares.
4. Sume el resultado del paso 2 al del paso 3
5. El dígito verificador es el número más pequeño que, sumado al valor del paso cuatro, da como resultado
un múltiplo de 10.
En nuestro ejemplo, la clave quedará formada como: 11372201/1
Apliquemos nuestro procedimiento a otras claves:
Clave original
15830824
23456735
12456779
13457558
33455648
Clave con dígito verificador
1 5 8 3 0 8 2 4/9
2 3 4 5 6 7 3 5/5
1 2 4 5 6 7 7 9/3
1 3 4 5 7 5 5 8/0
3 3 4 5 5 6 4 8/8
RECURSIÓN
Habrá podido observar que al definir la función factorial, utilizamos la variable num_fac para generar la
productoria, y luego asignarla a <factorial>, y tal vez se habrá preguntado por qué no se usó el identificador
factorial directamente. Esto se debe a una propiedad, llamada recursión (ó recursividad), que permite que
todo módulo -bajo ciertas condiciones-, se invoque a sí mismo. Tiene un uso muy frecuente en la programación de funciones matemáticas, que de por sí son recursivas, como la función factorial conocida. Veamos
cómo se define ésta matemáticamente:
X! =
x * (x-1)!
1
si x > 0
si x = 0
Respondiendo a ese modelo, podemos definir :
función fact(x:entero) : entero
comienza
si x = o entonces fact ← 1
fact ← x * fact(x - 1)
sino
termina
Nótese que la escritura del seudocódigo de la función es análoga a la definición del factorial. En particular,
esta propiedad se aplica cuando el modelo a programar es recursivo.
La recursión debe ser finita, es decir, debe haber por lo menos una salida no-recursiva del procedimiento o
función. En el caso anterior, se produce cuando x=0. En Estructuras de Datos y Algoritmos veremos Recursión con mayor profundidad.
APUNTES TEÓRICOS
- 26 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Tipos estructurados
Cuando definimos estructuras de datos pudimos observar que existen tipos simples estándares
y tipos estructurados o compuestos. Hasta ahora nos hemos manejado con tipos simples (entero, real, carácter, etc.), pero su utilización no es apropiada para la resolución de ciertos tipos de problemas.
Es por esto que existe la posibilidad de definir y utilizar tipos estructurados, entre los que se
encuentran los arreglos, registros, cadenas, archivos, y otros que veremos oportunamente.
Arreglos
En muchas ocasiones necesitamos agrupar variables que almacenen datos de un mismo tipo.
Supongamos, por ejemplo, que deseamos registrar la temperatura promedio mensual durante un año en la
ciudad de Comodoro Rivadavia.
Si utilizáramos los tipos de datos que conocemos hasta ahora, necesitaríamos declarar 12 variables reales distintas, una por cada mes, para almacenar dicha información. Es útil poder contar con alguna estructura que nos permita agrupar estos datos bajo un mismo nombre, y acceder individualmente a
cada uno de ellos. Esta estructura existe, y se denomina arreglo.
Arreglo: conjunto de celdas unidireccionables, las que almacenan elementos de un único
tipo. Se puede acceder directamente a cada una mediante su posición en el arreglo, la que está determinada por el o los índices
Los arreglos se clasifican en dos grupos:
• unidimensionales (llamados también vectores): poseen una única dimensión, es decir, cada posición es
accesible mediante un único índice. En nuestro ejemplo de las temperaturas promedio, necesitaríamos
indicar sólo el mes para obtener la temperatura promedio del mismo.
• multidimensionales (por ejemplo, las matrices): poseen más de una dimensión, lo que equivale a decir
que cada elemento dentro de ellos se direcciona mediante dos o más índices. Las matrices son un caso
particular de los arreglos multidimensionales, pues poseen 2 dimensiones. Para ilustrar este concepto,
consideremos ahora la necesidad de registrar las temperaturas promedio mensuales de los últimos 4
años. Podríamos utilizar una tabla como la que sigue:
Ene
Feb
Mar
Abr
May
Jun
Jul
Ago
Sep
Oct
Nov
Dic
1994
1995
1996
1997
Para acceder a un dato de esta tabla necesitamos especificar el año y el mes, es decir, necesitamos dos índices.
El ejemplo anterior responde a una definición bidimensional (matriz), pero podríamos necesitar
arreglos de más de dos dimensiones, como en el siguiente caso: deseamos mantener la información de las
temperaturas promedio mensuales de los últimos 3 años por provincia. En este caso necesitamos un arreglo
tridimensional, al cual se acceda mediante 3 índices: provincia, año y mes,
Como conclusión podemos destacar que si bien en esta asignatura sólo utilizaremos arreglos
unidimensionales y bidimensionales, es posible definirlos n-dimensionales.
APUNTES TEÓRICOS
- 27 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Arreglos Unidimensionales: Vectores
• DECLARACIÓN DE UN TIPO VECTOR
Para poder utilizar una variable de tipo vector es necesario declarar este tipo en la sección de
declaración de tipos del programa y luego declarar la variable como de ese tipo.
La declaración del tipo se realiza de la siguiente forma:
Tipos
<identificador_de_tipo> = Arreglo (n) de <tipo_elemento>
donde <identificador_de_tipo> es el nombre que se asigna al tipo y n es la cantidad de elementos del tipo
<tipo_elemento> que puede contener el arreglo. Cabe aclarar que <tipo_elemento> puede ser cualquier
estructura de dato (simple o compuesta)
Ejemplo:
Tipos
VEC_ENT = arreglo(100) de enteros
En este caso hemos declarado un tipo denominado VEC_ENT que define un arreglo unidimensional de 100 elementos de tipo entero.
• DECLARACIÓN DE VARIABLES DE UN TIPO VECTOR
Variables
<identificador_de_variable>:<tipo_vector>
donde <identificador_de_variable> es el nombre que se desea asignar a la variable y <tipo_vector> es el
identificador del tipo definido previamente.
Ejemplo:
Tipos
VEC_REAL = arreglo(12) de reales
Variables
VECTOR_TEMPERATURAS : VEC_REAL
El acceso a una componente determinada del vector se realiza indicando el nombre de la variable acompañado de un subíndice encerrado entre paréntesis, el cual indicará la posición dentro del vector.
VECTOR_TEMPERATURAS
29.5
28.0
27.9
22.6
15.2
14.1
12.9
9.7
14.4
18.6
23.1
31.4
1
2
3
4
5
6
7
8
9
10
11
12
INDICE
En nuestro ejemplo, si queremos hacer referencia a la temperatura de Abril y suponiendo que
cada posición de VECTOR_TEMPERATURAS almacena la temperatura del mes cuyo número corresponde
con el índice, usamos la notación:
VECTOR_TEMPERATURAS(4)
Si queremos asignar una nueva temperatura al mes de Diciembre, que se almacena en la posición 12 del vector, expresamos:
VECTOR_TEMPERATURAS(12) ← 31.4
• OPERACIONES SOBRE VECTORES
Lectura: equivale a leer cada una de las componentes del vector individualmente.
APUNTES TEÓRICOS
- 28 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Ejemplo:
Procedimiento LEO_VECTOR ( N:entero; ref VEC : VEC_REAL )
Variables
i:entero
Comienza
para i ← 1 hasta N hacer
leer VEC(i)
Termina
Impresión: equivale a imprimir cada una de las componentes del vector en forma individual.
Procedimiento IMP_VECTOR (N:entero; VEC:VEC_REAL)
Variables
i:entero
Comienza
para i ← 1 hasta N hacer
escribir VEC(i)
Termina
Procesamiento de un vector: veamos algunos ejemplos de procesamiento de vectores.
Ejemplo 1:
Procedimiento CUENTA_NULOS (N:entero; VEC:VEC_REAL; ref CANT:entero)
{ Este procedimiento cuenta la cantidad de componentes nulas que tiene el vector y la almacena en
CANT }
Variables
i : entero
Comienza
CANT ← 0
para i ← 1 hasta N hacer
si VEC(i) = 0 entonces
CANT ← CANT+1
Termina
Ejemplo 2:
Procedimiento MAX_MIN (N:entero; VEC:VEC_REAL; ref Pos_MAX, Pos_MIN: entero)
{ Este procedimiento obtiene la posición de los valores máximo y mínimo de un vector, }
Variables
i : entero
Comienza
POS_MAX ← 1
POS_MIN ← 1
para i ← 2 hasta N hacer { comenzamos con la segunda componente del vector porque la primera es
utilizada para asignar el valor inicial a Pos_MIN y a Pos_MAX }
si VEC(i) < VEC(POS_MIN ) entonces POS_MIN ← i
sino
si VEC(i) > VEC(POS_MAX) entonces POS_MAX ← i
APUNTES TEÓRICOS
- 29 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Termina
Ejemplo 3:
Procedimiento GENERA_VECTOR (N:entero; REF VEC: VEC_REAL)
{El siguiente procedimiento almacena en cada componente del vector la raíz cuadrada de un valor leído}
Variables
VALOR, i : entero
Comienza
para i ← 1 hasta N hacer
Comienza
leer VALOR
VEC(i) ←
Termina
VALOR
Termina
Importante: es necesario distinguir entre lectura y generación de vectores. Cuando se lee un vector los
valores que corresponden a cada componente del vector han sido ingresados como componentes de un vector Si no es así, el vector es generado con valores de variables de un uso particular.
ORDENAMIENTO Y BÚSQUEDA SOBRE VECTORES
Ordenar un vector significa reubicar sus componentes de tal forma que se cumpla alguna relación de orden (menor < , menor ó igual ≤, mayor >, mayor ó igual ≥ ) entre todas sus componentes.
En diversas aplicaciones se necesita tener ordenadas las componentes del vector según algún
criterio (en forma ascendente o descendente), por lo que veremos a continuación varios métodos utilizados
para tal fin. Consideraremos en todos los casos una ordenación ascendente, pero es muy sencillo adaptar
los métodos para otro criterio de ordenación.
1.- Método de Ordenamiento por Selección
Este método buscar el menor elemento del vector y lo coloca en la primera posición; luego el menor entre los restantes -del vector- y lo ubica en la segunda posición, y así sucesivamente hasta llegar a un vector
de dimensión 1
Los pasos para ordenar un vector aplicando este método se pueden esquematizar así:
1. Buscar el menor elemento entre los n que componen el vector.
2. Intercambiar dicho elemento con el que se encuentra en la 1º posición.
3. Encontrar el elemento mínimo entre los n-1 restantes, e intercambiarlo con el que se encuentre en la
posición 2.
4. Repetir este proceso con los n-2 elementos restantes, y así sucesivamente hasta que el proceso se realice entre 1 componente del vector.
Veamos a continuación cómo se transforma el vector
X=
36
24
10
6
12
Posiciones
inicial
Mínimo
1
2
3
4
5
36
24
10
6
12
APUNTES TEÓRICOS
- 30 -
6
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Primera iteración
6
24
10
36
12
10
Segunda iteración
6
10
24
36
12
12
Tercera iteración
6
10
12
36
24
24
Cuarta iteración
6
10
12
24
36
A partir del vector inicial obtenemos el mínimo elemento que es 6 y está en la 4º posición; en la
primera iteración lo intercambiamos con el elemento que se encuentra en la 1º posición. De los 4 elementos
restantes, obtenemos el menor, que es 10 y se encuentra en la 3º posición. Lo intercambiamos en la segunda iteración con el elemento de la posición 2. Así continuamos hasta que el vector esté ordenado.
Para simplificar la codificación del algorítmo utilizaremos una función que calcula la posición del
mínimo elemento de un vector.
Función Posi_Mínimo (VEC_LOCAL:VEC_ENTERO; N,POSI_PRIM: entero) : entero
{Calcula la posición del mínimo elemento de un vector VEC_LOCAL de N elementos}
Variables
i, i_min: entero
Comienza
i_min ← POSI_PRIM
para i ← POSI_PRIM + 1 hasta N hacer
si VEC_LOCAL(i) < VEC_LOCAL(i_min) entonces i_min ← i
Posi_Mínimo ← i_min
Termina
El siguiente algoritmo nos permite aplicar el método de selección a un vector:
Procedimiento Seleccion (ref VEC:VEC_ENTERO; DIM:entero)
{ DIM es la cantidad de elementos del vector }
Variables
i,posi_min,auxiliar: entero
Comienza
para i ← 1 hasta DIM - 1 hacer
Comienza
posi_min ← Posi_Mínimo(VEC, DIM, i )
auxiliar ← VEC(i)
VEC(i) ← VEC(posi_min)
VEC(posi_min) ← auxiliar
Termina
Termina
2.- Método de Ordenamiento BURBUJA
Este método se basa en el principio de comparar pares de componentes contiguas e intercambiarlas entre sí, si fuera necesario, hasta que estén todas ordenadas. Podría decirse que los valores mayores “burbujean” hasta el final de la lista, y los pequeños se “hunden” hacia el principio de la lista. Consideremos un
ejemplo concreto en el que ordenaremos un vector de 5 posiciones:
Posiciones
1
2
3
4
5
inicial
36
24
10
6
12
Primera iteración
24
10
6
12
36
Segunda iteración
10
6
12
24
36
APUNTES TEÓRICOS
- 31 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Tercera iteración
6
10
12
24
36
Cuarta iteración
6
10
12
24
36
En la primera iteración se comparan VEC(1)=36 y VEC(2)=24. Como 36 > 24 se intercambian
entre sí. Luego se comparan VEC(2)=36 y VEC(3)=10. Al ser 36 > 10, nuevamente se intercambian. El proceso continua en forma similar hasta realizar todas las comparaciones. Se observa que al final de la primera
iteración el elemento 36 “burbujeó” hasta el final del vector.
Se incluyeron en el gráfico todas las iteraciones para que el lector pueda realizar el seguimiento
de este método de ordenación.
El algoritmo para ordenar mediante el método de burbuja es el siguiente:
Procedimiento Burbuja1 (ref VEC:VEC_ENTERO; DIM:entero)
{ DIM es la cantidad de elementos del vector }
Variables
i,j,aux: entero
Comienza
para i ← 1 hasta DIM hacer
para j ← 1 hasta DIM - i hacer
si VEC(j) > VEC(j+1) entonces { deben intercambiarse los elementos }
comienza
aux ← VEC(j)
VEC(j) ← VEC(j+1)
VEC(j+1) ← aux
termina
Termina
Obsérvese que si en una iteración no se realizan intercambios, significa que el vector ya está ordenado.
Podríamos desear interrumpir las iteraciones si se verifica la condición descrita. A continuación se presenta
una versión del algortimo de ordenamiento burbuja que testea si se realizaron intercambios o no para saber
si el vector ya está ordenado y de esta manera no continuar el proceso.
Procedimiento Burbuja2( ref VEC:VEC_ENTERO; DIM:entero)
{ DIM es la cantidad de elementos del vector }
Variables
i,tope,aux: entero
cambio: lógico
Comienza
tope ← DIM
cambio ← verdadero
mientras tope > 1 ∧ cambio hacer
comienza
cambio ← falso
para i ← 1 hasta tope -1 hacer
si VEC(j) > VEC(j+1) entonces { deben intercambiarse los elementos }
comienza
aux ← VEC(j)
VEC(j) ← VEC(j+1)
VEC(j+1) ← aux
cambio ← verdadero
termina
tope ← tope -1
termina
Termina
APUNTES TEÓRICOS
- 32 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
3.- Método de Ordenamiento por Inserción.
Este método de ordenamiento se basa en comparaciones y desplazamientos sucesivos. Cada
elemento del vector es insertado en el lugar correspondiente respecto a los otros elementos ya ordenados.
Inicialmente se ordenan los dos primeros elementos. Luego, se compara el tercer elemento con
los ya ordenados para buscar la posición que le corresponda respecto a los mismos. Si fuese necesario, se
desplazan los elementos posteriores hacia la derecha para liberar la posición del vector donde se insertará
el elemento considerado. Se repite esta operación con todos lo elementos restantes.
A continuación aplicaremos el método a nuestro vector:
Posiciones
1
2
3
4
5
inicial
36
24
10
6
12
Primera iteración
24
36
10
6
12
Segunda iteración
10
24
36
6
12
Tercera iteración
6
10
24
36
12
Cuarta iteración
6
10
12
24
36
En la primera iteración se comparan VEC(1)=36 y VEC(2)=24. Como 36 > 24, se intercambian.
En la segunda iteración se considera VEC(3)=10, y al compararlo con los dos elementos ya
ordenados, se encuentra que debe ubicarse en la primer posición del vector. Se desplazan un lugar a la
derecha los elementos que se encuentran en las dos primeras posiciones para liberar la posición 1, donde
se ubica el 10.
En la tercera iteración comparamos VEC(4)=6 con los tres anteriores, ya ordenados. Encontramos que, por ser menor que 10, debería colocarse en la 1º posición. Entonces desplazamos los elementos 10, 24 y 36 una posición a la derecha para poder hacerlo.
Siguiendo el razonamiento anterior, VEC(5)=12 debe ubicarse entre el 10 y el 24, por lo que
desplazamos el 24 y el 36 un lugar a la derecha para colocar el 12.
El algoritmo que nos permite ordenar un vector mediante este método es el siguiente:
Procedimiento Inserción (ref VEC:VEC_ENTERO; DIM:entero)
Variables
i,j,k,aux:entero
Comienza
si VEC(1) > VEC(2) entonces
comienza
aux ← VEC(1)
VEC(1) ← VEC(2)
VEC(2) ← aux
termina
para i ← 3 hasta DIM hacer
comienza
k←1
mientras VEC(k) < VEC(i) ∧ k < i hacer
k←k+1
aux ← VEC(i)
para j ← i decremento k + 1 hacer
VEC(j) ← VEC(j - 1)
APUNTES TEÓRICOS
- 33 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
VEC(k) ← aux
termina
Termina
4.- Método de Ordenamiento De a Pares
El principio de este método es el siguiente: se toman los elementos de las posiciones 1 y 2 del
vector y se los ordena, colocando el mayor de ellos en la posición 2. Luego se repite el procedimiento con
los elementos de las posiciones 3 y 4, 5 y 6, etc. Una vez recorrido todo el vector aplicando el proceso descrito, se realiza la misma operación comenzando con el par de elementos de las posiciones 2 y 3, luego 4 y
5, etc. Se continúan aplicando estos dos procesos en forma alternada hasta que el vector esté ordenado.
Posiciones
1
2
3
4
5
inicial
36
24
10
6
12
Primera iteración
24
36
6
10
12
Segunda iteración
24
6
36
10
12
Tercera iteración
6
24
10
36
12
Cuarta iteración
6
10
12
24
36
Para saber si el vector ya está ordenado, utilizamos una marca que indica si se produjeron
cambios. Si no los hubo, el vector ya está ordenado.
Procedimiento Ordena_Pares (ref VEC: VEC_ENTERO; DIM: entero)
Variables
hay_cambio, primera_vez: lógico
posi_comienzo, i, AUX: entero
Comienza
primera_vez ← verdadero
hay_cambio ← verdadero
posi_comienzo ← 1
mientras hay_cambio ∨ primera_vez hacer
comienza
hay_cambio ← falso
i ← posi_comienzo
mientras i < DIM hacer
comienza
si VEC(i) > VEC(i+1) entonces
comienza
aux ← VEC(i)
VEC(i) ← VEC(i+1)
VEC(i+1) ← aux
hay_cambio ← verdadero
termina
i ← i+2
termina
si posi_comienzo = 1
entonces posi_comienzo ← 2
APUNTES TEÓRICOS
- 34 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
sino comienza
posi_comienzo ← 1
primera_vez ← falso
termina
termina
Termina
5.- Método de Ordenamiento de la Sacudida
El principio de este método es el mismo que el del ordenamiento BURBUJA, con la diferencia
que el límite de comparación, en lugar de ir decrementándose en 1 en cada iteración, se fija en la posición
del vector donde se realizó el último cambio, evitando comparaciones sobre elementos ya ordenados.
Posiciones
Límite
1
2
3
4
5
inicial
36
24
10
6
12
Primera iteración
24
10
6
12
36
5
Segunda iteración
10
6
12
24
36
4
Tercera iteración
6
10
12
24
36
2
Cuarta iteración
6
10
12
24
36
En el ejemplo se observa que hasta la segunda iteración el comportamiento del método de
ordenamiento es similar al burbuja, pero en la tercera pude verse la diferencia: el límite superior (tope) no se
decrementa en uno, sino que contiene la posición del último elemento que fue intercambiado.
Procedimiento Sacudida (ref VEC:VEC_ENTERO; DIM:entero)
{ DIM es la cantidad de elementos del vector }
Variables
i,tope,aux,posi: entero
cambio: lógico
Comienza
tope ← DIM
posi ← 1
cambio ← verdadero
mientras tope > 1 ∧ cambio hacer
comienza
cambio ← falso
para j ← 1 hasta tope -1 hacer
si VEC(j) > VEC(j+1) entonces { deben intercambiarse los elementos }
comienza
{ y registrarse el nuevo límite }
aux ← VEC(j)
VEC(j) ← VEC(j+1)
VEC(j+1) ← aux
cambio ← verdadero
posi ← j
termina
tope ← posi
termina
Termina
APUNTES TEÓRICOS
- 35 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
6.- Método de Ordenamiento Shell
Este método se basa en comparar pares de elementos que se encuentren almacenados en
posiciones separadas por una distancia D, y se los intercambia, si fuera necesario, para su ordenamiento.
En la primera iteración, D=(N+1)/2, con lo cual se comparan el elemento ubicado en la posición I con el que
está en la posición I+D, con 1 ≤ I < D. En las sucesivas iteraciones, se redefine D como (D+1)/2 (la mitad del
D anterior). Como siempre se está comparando el elemento I con el I+D, en cada redefinición de D se incrementa la cantidad de comparaciones al doble. Cuando D es 1, el método se convierte en burbuja.
Posiciones
1
2
3
4
5
6
7
8
9
inicial
36
24
10
6
12
31
33
40
45
Primera iteración D=5
31
24
10
6
12
36
33
40
45
Segunda iteración D=3
6
12
10
31
24
36
33
40
45
Tercera iteración D=2
6
12
10
31
24
36
33
40
45
Cuarta iteración
6
10
12
24
31
33
36
40
45
D=1
En el ejemplo propuesto arriba, se observa que en la primera iteración, con D=5 porque (N+1)/2
= (9 + 1)/2 = 5, se comparan los elementos que se encuentran en las posiciones 1 y 6 y se los intercambia,
porque 31 < 36. Luego se comparan los elementos de las posiciones 2 y 7, 3 y 8, y 4 y 9, y se intercambian
si es necesario. En la segunda iteración D = (D+1)/2 = (5+1)/2 = 3. Se sigue entonces idéntico procedimiento que en la primera iteración, tomando ahora los pares de posiciones (1,4), (2,5), (3,6), (4,7), (5,8) y (6,9),
comparándolos e intercambiándolos cuando sea el caso. En la tercera iteración D=2, y en la cuarta 1, con lo
que equivale al método burbuja.
Procedimiento Shell (ref VEC : VEC_ENTERO ; DIM:entero)
Variables
D,i,aux:entero
Comienza
D ← [(DIM+1)/2]
mientras D > 1 hacer
comienza
para i ← 1 hasta DIM-D hacer
si VEC(i) > VEC(i+D) entonces
comienza
aux ← VEC(i)
VEC(i) ← VEC(i+D)
VEC(i+D) ← aux
termina
D ← [(D+1)/2]
termina
Burbuja(VEC, DIM)
Termina
BÚSQUEDA
En muchas aplicaciones es necesario buscar un elemento dentro de una determinada estructura de datos (vector, matriz, archivo, etc.). Puede resultar que en la búsqueda encontremos dicho elemento,
pudiendo indicar dónde, o que no lo encontremos.
APUNTES TEÓRICOS
- 36 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
De acuerdo a las características de la búsqueda, podemos diferenciar dos métodos:
♦ Búsqueda lineal: consiste en recorrer secuencialmente la estructura de datos a partir del primer ele-
mento y comparar cada elemento con el buscado hasta encontrarlo o hasta que no queden elementos
para comparar. Si ocurre este último caso, la búsqueda ha terminado sin éxito.
♦ Búsqueda binaria: generalmente mucho más rápido que el anterior, este método requiere que la estruc-
tura de datos sobre la que se realizará la búsqueda se encuentre ordenada. Compara el elemento buscado con el el elemento central de la estructura . Si el elemento buscado coincide con el elemento central, se termina la búsqueda. Si el elemento buscado es menor que el central, se considera la primera mitad de la estructura, y se ubica el elemento central de dicha mitad, y se lo compara con el buscado. Se
repite este proceso hasta que se encuentra el elemento buscado o hasta que no queden más elementos
por comparar.
Ejemplo: búsqueda lineal sobre un vector no ordenado
Procedimiento Buscar (VEC:VEC_ENTERO; ELEMENTO,DIM:entero; ref POSI:entero)
{ POSI contendrá la posición del vector en la que se encontró el elemento buscado -ELEMENTO- o 0
si no se encontró }
Variables
i:entero
Comienza
POSI ← 0
i←1
mientras (POSI = 0) y (i ≤ DIM) hacer
si VEC(i) = ELEMENTO entonces
POSI ← i
sino
i ← i+1
Termina
Ejemplo: búsqueda lineal sobre un vector ordenado
La eficiencia de la búsqueda lineal puede mejorar si se realiza sobre un vector ordenado, porque sólo será necesario recorrer el vector hasta la posición donde se encuentre el elemento buscado o uno
mayor a éste.
Procedimiento Buscar (VEC:VEC_ENTERO; ELEMENTO,DIM:entero; ref POSI:entero)
{ POSI contendrá la posición del vector en la que se encontró el elemento buscado -ELEMENTO- o 0
si no se encontró. El vector está ordenado }
Variables
i:entero
Comienza
POSI ← 0
i←0
terminado ← falso
mientras (i ≤ DIM) y no terminado hacer
comienza
i←i+1
si VEC(i) = ELEMENTO entonces
comienza
APUNTES TEÓRICOS
- 37 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
POSI ← i
terminado ← verdadero
termina
sino
si VEC(i) > ELEMENTO entonces
comienza
terminado ← verdadero
POSI ← 0
termina
termina
Termina
Ejemplo: búsqueda binaria
Procedimiento Busqueda_binaria (VEC:VEC_ENTERO; ELEMENTO,DIM:entero; ref POSI:entero)
{ POSI contendrá la posición del vector en la que se encontró el elemento buscado -ELEMENTO- o 0
si no se encontró. VEC está ordenado de menor a mayor }
Variables
inicial, final, punto_medio:entero
encontrado: lógico
Comienza
inicial ← 1
final ← DIM
encontrado ← falso
POSI ← 0 { si el elemento no se encuentra, posi ya está en 0 }
mientras inicial ≤ final ∧ no encontrado hacer
comienza
punto_medio ← [(inicial + final)/2]
si VEC(punto_medio) = ELEMENTO entonces
comienza
POSI ← punto_medio
encontrado ← verdadero
termina
sino
si VEC(punto_medio) > ELEMENTO entonces
final ← punto_medio -1 { el elemento está en la 1º mitad }
sino
inicial ← punto_medio + 1 { el elemento está en la 2º mitad }
termina
Termina
Inicialmente, punto_medio es la posición central del vector (Inicial=1 , Final=DIM). Si el elemento buscado
es mayor que el correspondiante a la posición de punto_medio, se fija Inicial como la posición siguiente a
punto_medio (se descarta la primer mitad del vector). Si por el contrario, el elemento buscado es menor que
de la posición de punto_medio, se toma como Final la posición anterior a punto_medio, desechándose la
segunda mitad del vector. El nuevo punto medio es la posición central del vector comprendido entre las
posiciones Inicial y Final.
Si al comparar el elemento de la posición punto_medio con el buscado encontramos que ambos coinciden, ha finalizado la búsqueda de manera exitosa. Cuando la posición inicial es mayor que la final
significa que el elemento buscado no se encuentra dentro del vector.
APUNTES TEÓRICOS
- 38 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Arreglos Bidimensionales : Matrices
Una matriz es un tipo de datos estructurado, un caso particular de arreglos multidimensionales.
Está formada por una colección finita de elementos, todos del mismo tipo ordenados en dos dimensiones.
Para acceder a cada componente de la matriz se utilizan dos índices, el primero referencia la posición del
elemento en la primera dimensión (filas) y el segundo índice se refiere a la posición del elemento en la segunda dimensión (columnas).
• DEFINICIÓN DE UN TIPO MATRIZ
Para poder utilizar una variable de tipo matriz es necesario declarar este tipo en la sección de
declaración de tipos del programa y luego declarar la variable como de ese tipo.
La declaración del tipo se realiza de la siguiente forma:
Tipos
<identificador_de_tipo> = Arreglo (m,n) de <tipo_elemento>
donde:
• <identificador_de_tipo> es el nombre que se asigna al tipo,
• m es la cantidad de elementos de <tipo_elemento> que puede contener cada fila del arreglo,
• n es la cantidad de elementos de <tipo_elemento> que puede contener cada columna del arreglo.
Cabe aclarar que <tipo_elemento> puede ser cualquier estructura de dato (simple o compuesta)
⇒ Ejemplo:
Tipos
MAT_ENT = arreglo(3,5) de enteros
En este caso hemos declarado un tipo denominado MAT_ENT que define un arreglo bidimensional de 3 filas por 5 columnas de elementos de tipo entero.
• DECLARACIÓN DE VARIABLES DE UN TIPO MATRIZ
Variables
<identificador_de_variable>:<tipo_matriz>
donde <identificador_de_variable> es el nombre que se desea asignar a la variable y <tipo_matriz> es el
identificador del tipo definido previamente.
⇒ Ejemplo:
Tipos
MAT_REAL = arreglo(4, 12) de reales
MAT_ENTERO = arreglo(5, 12) de enteros
Variables
MATRIZ_TEMPERATURAS: MAT_REAL
El acceso a una componente determinada de la matriz se realiza indicando el nombre de la
variable acompañado de dos subíndices encerrados entre paréntesis, que indicarán la fila y la columna que
determinan la posición del dato dentro de la matriz.
Indices
1
2
3
4
1
2
3
4
5
6
7
8
9
10
11
12
29.5
32.4
31.8
33.7
28.0
29.2
26.6
28.8
27.9
26.9
25.7
26.3
21.6
23.5
22.8
20.1
11.5
13.4
15.2
14.9
14.1
13.8
14.2
14.1
11.8
10.9
13.1
11.2
5.7
6.3
6.2
6.1
14.4
12.3
13.8
12.8
18.6
19.7
14.6
13.3
23.1
22.4
23.8
22.3
34.6
32.5
31.4
32.1
Ene
Feb
Mar
Abr
May
Jun
Jul
Ago
Set
Oct
Nov
Dic
APUNTES TEÓRICOS
- 39 -
1994
1995
1996
1997
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
En nuestro ejemplo, cada posición de la Matriz MATRIZ_TEMPERATURAS almacena la temperatura promedio del mes y año cuyos números se corresponden con los índices. Si queremos hacer referencia a la temperatura de Junio del año 1995, usamos la notación:
MATRIZ_TEMPERATURAS(2,6)
Si queremos asignar una nueva temperatura al mes de Octubre de 1996, que se almacena en
la posición (3,10) de la matriz, expresamos:
MATRIZ_TEMPERATURAS(3,10) ← 20.4
• OPERACIONES SOBRE MATRICES
⌦
Lectura: lee cada una de las componentes de la matriz individualmente.
Ejemplo:
Procedimiento LEO_MATRIZ ( M,N:entero; ref MAT:MAT_REAL )
Variables
i, j:entero
Comienza
para i ← 1 hasta M hacer
para j ← 1 hasta N hacer
leer MAT(i, j)
Termina
⌦
Impresión: imprime cada una de las componentes del vector en forma individual.
Procedimiento IMP_MATRIZ (M,N:entero; MAT:MAT_REAL)
Variables
i, j:entero
Comienza
para i ← 1 hasta M hacer
para j ← 1 hasta N hacer
escribir MAT(i, j)
Termina
⌦
Impresión detallada: imprime literalmente cada una de las componentes del vector (cadena
identificatoria y contenido, por fila)
Procedimiento IMP2_MATRIZ (M,N:entero; MAT:MAT_REAL)
Variables
i, j:entero
Comienza
para i ← 1 hasta M hacer
comienza
para j ← 1 hasta N hacer
escribir ’matriz(‘, i, ‘,’,j,’)=‘, MAT(i, j)
APUNTES TEÓRICOS
- 40 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
escribirlínea
termina
Termina
Supongamos que queremos imprimir una matriz de 5 x 4; con este procedimiento saldría impreso de la
siguiente manera:
matriz(1,1)= 2.3
matriz(2,1)=-2.43
matriz(3,1)= 12.8
matriz(4,1)= 31.3
matriz(5,1)= 11.8
⌦
matriz(1,2)= 4.8
matriz(2,2)= 5.7
matriz(3,2)= -2.7
matriz(4,2)= 4.8
matriz(5,2)= - 5.4
matriz(1,3)= 2.53
matriz(2,3)= 4.3
matriz(3,3)= -2.8
matriz(4,3)= 46.7
matriz(5,3)= 12.9
matriz(1,4)= 5.4
matriz(2,4)= 7.38
matriz(3,4)= 12.9
matriz(4,4)= 32.8
matriz(5,4)= 12.6
Procesamiento de una matriz: veamos algunos ejemplos de procesamiento de matrices.
Ejemplo 1:
Procedimiento SUMA_FILAS (M,N:entero; MAT:MAT_REAL; ref VEC_SUMA:VEC_REAL)
{ Este procedimiento suma los elementos de cada fila de la matriz y almacena los resultados en
VEC_SUMA, que es un vector de M componentes }
Variables
i, j, Sum: entero
Comienza
para i ← 1 hasta M hacer
Comienza
Sum ← 0
para j ← 1 hasta N hacer
Sum ← Sum+ MAT(i, j)
VEC_SUMA (i) ← Sum
Termina
Termina
Ejemplo 2:
Procedimiento MAX_MIN (M,N:entero; MAT:MAT_REAL; ref MAX, MIN:real)
{ Este procedimiento obtiene los valores máximo y mínimo de una matriz, almacenándolos en MAX y
MIN, respectivamente }
Variables
i, j : entero
Comienza
MAX ← MAT(1,1)
MIN ← MAT(1,1)
para i ← 1 hasta M hacer
para j ← 1 hasta N hacer
si MAT(i, j) < MIN entonces
MIN ← MAT(i, j)
sino
si MAT(i, j) > MAX entonces
MAX ← MAT(i, j)
Termina
Ejemplo 3:
APUNTES TEÓRICOS
- 41 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Procedimiento GENERA_MATRIZ (M, N:entero; REF MAT: MAT_ENTERO)
{ El siguiente procedimiento almacena en cada fila de la matriz nro_legajo, cod_asignatura y el promedio de las notas leidas}
Variables
i, nro_legajo, cod_asignatura: entero
nota_1er_cuatrim, nota_2do_cuatrim: entero
Comienza
para i ← 1 hasta M hacer
Comienza
leer nro_legajo, nota_1er_cuatrim, nota_2do_cuatrim
MAT(i,1) ← nro_legajo
MAT(i,2) ← cod_asignatura
MAT(i,3) ← [(nota_1er_cuatrim + nota_2do_cuatrim) / 2]
Termina
Termina
Importante: es necesario distinguir entre lectura y generación de matrices. Cuando se lee una matriz, los
valores que corresponden a cada componente de la misma han sido ingresados directamente
como valores matriciales; en caso contrario, utilizamos la matriz como soporte de la información para procesarla y ésta es generada así.
• ORDENAMIENTO SOBRE MATRICES
Ordenar una matriz significa reubicar sus componentes de tal forma que se cumpla alguna
relación de orden (menor < , menor ó igual ≤, mayor >, mayor ó igual ≥ ) entre sus componentes.
El ordenamiento de los elementos de una matriz se realiza teniendo en cuenta una columna J
en particular; para ello se debe tener en cuenta que la comparación será de los elementos de la columna J
en las diferentes filas. Si debe realizarse una permuta, ésta debe efectuarse por completo en las filas correspondientes.
Procedimiento para ordenar una matriz por columnas:
Como en el caso de los vectores, consideraremos en todos los casos una ordenación ascendente, pero es muy sencillo adaptar los métodos para una ordenación descendente.
Supongamos que COL es la columna según la cual ordenaremos la matriz. El procedimiento
Burbuja a aplicar es el siguiente:
Procedimiento ORDEN_MAT1 (M, N, COL: entero, ref A: MAT_ENTERO)
Variables:
i, j, Tope: entero
Aux: entero
Cambio: Lógico
Comienza
Tope ← N
repetir
cambio ← falso
Para i ← 1 hasta Tope - 1 Hacer
Si A( i, COL) > A( i+1, COL) Entonces
Comienza
Cambio ← Verdadero
Para J ←1 hasta M Hacer
Comienza
APUNTES TEÓRICOS
- 42 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Aux ← A( i, j)
A(i, j) ← A(i+1, j)
A(i+1, j) ← Aux
Termina
Termina
Tope ← Tope-1
hasta Tope = 1 ∨ no cambio
Termina
Observaciones: Tener en cuenta que si la matriz posee elementos repetidos, se debe utilizar una segunda
columna de ordenamiento.Si es previsible dicha situación, debemos conocer otra columna
COL2. Utilizamos para ello el siguiente algoritmo:
Procedimiento ORDEN_MAT2 (M, N, COL, COL2: entero, ref A: MAT_ENTERO)
Variables:
i, j, Tope: entero
Aux: entero
Cambio: Lógico
Comienza
Tope ← N
Cambio ← Verdadero
repetir
Cambio ← Falso
Para i ← 1 hasta Tope - 1 Hacer
Si A(i,COL) ≥ A(i+1,COL) ∨ A (i,COL2) > A(i+1,COL2)) Entonces
Comienza
Cambio ← Verdadero
Para J ←1 hasta M Hacer
Comienza
Aux ← A( i, j)
A(i, j) ← A(i+1, j)
A(i+1, j) ← Aux
Termina
Termina
Tope ← Tope-1
hasta tope = 1 v no cambio
Termina
• BUSQUEDA SOBRE MATRICES
Para realizar una búsqueda en una matriz, también consideramos una columna determinada.
Podemos utilizar tanto la búsqueda secuencial como la binaria, teniendo en cuenta que para esta última, la
matriz debe estar ordenada por la columna de búsqueda.
Veremos a continuación un ejemplo de búsqueda binaria en una matriz, considerando una columna COL.
Procedimiento BuscoEnMat (MAT:MAT_ENTERO; N,M,COL,Buscado:entero; ref NFil:entero)
{ NFil contendrá en nro. de fila de la matriz en la que se encontró el elemento buscado dentro de la
columna COL; si es 0 significa que el elemento no se encontró}
Variables
PI, PF, Medio: entero
Encontrado: lógico
Comienza
APUNTES TEÓRICOS
- 43 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
NFil ← 0
Encontrado ← Falso
PI ← 1
PF ← M
mientras PI ≤ PF ^ no encontrado hacer
comienza
Medio ← [(PI + PF) / 2]
si MAT(Medio, Col) = Buscado entonces
comienza
NFil ← Medio
encontrado ← verdadero
termina
sino
si MAT(Medio, Col) > Buscado entonces
PF ← Medio - 1
sino
PI ← Medio + 1
termina
termina
Aplicación de cadenas y arreglos en seguridad de la Información: Encriptado
En el anexo de Seguridad de la Información, hemos visto el concepto de la misma, como así también,
cómo la Criptología pretende resolver los problemas de seguridad en la comunicación dedatos. En nuestra
materia, simplemente veremos un método sencillo de encriptar un vector, y cómo desencriptarlo:
En primer lugar, haremos una matriz de correspondencia entre pares de caracteres:
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
C
w
J
e
M
V
A
b
O
a
c
f
Z
E
d
B
g
k
I
T
U
V
W
X
Y
Z
a
b
c
d
e
f
g
h
i
j
k
l
x
L
j
p
T
h
F
i
K
N
l
D
m
S
n
G
o
Y
W
m
n
o
p
q
r
s
t
u
v
w
x
y
z
.
,
;
U
q
;
H
v
y
R
.
z
r
P
s
,
t
u
Q
X
≠
1
2
3
4
5
6
7
8
9
0
*
/
&
#
@
+
<
>
^
%
Si quisiéramos encriptar el siguiente mensaje:
Nuestra cita informática virtual la haremos en el Jardín Japonés,
a las 7 p.m., bajo la madreselva en flor.
Aplicando nuestra tabla de transformación quedará:
APUNTES TEÓRICOS
- 44 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
EzDR.yi≠NG.i≠Gqm;yUi.GNi≠rGy.ziW≠Wi≠niyDU;R≠Dq≠DW≠aiyl
Gq≠aiH;qDRQ≠i≠WiR≠<≠HuUuQ≠Kio;≠Wi≠UiIyDRDWri≠Dq≠mW;yu.
El que quiera traducirlo, deberá usar esa tabla en el sentido contrario. Dejamos para la clase práctica
el desarrollo del algoritmo.
REGISTROS
Es oportuno aclarar que hasta ahora todas las operaciones realizadas sobre un conjunto de
datos, imponían la condición necesaria de homogeneidad de la estructura utilizada para contener a dichos
datos.
¿Qué sucede si, dadas las características del problema, necesitamos de una estructura de
datos cuyo contenido sea no homogéneo ?
Es así que aparece el tipo de dato registro, el cual tiene la característica de permitir identificar
unívocamente un conjunto de datos que pueden ser de tipos diferentes (carácter, entero, real, etc.)
Un registro se compone de campos, en los que se almacena la información no homogénea,
cada campo se asocia a un identificador - identificador de campo -, y cada registro tiene su identificador identificador de registro-. Se puede manipular el registro completo para una asignación, o lectura/grabación
en un archivo, pero en general vamos a necesitar operar con los campos de un registro. En este caso, el
acceso a cada campo tiene el siguiente formato:
<identificador_de_registro > “.” <identificador de campo>
Sea la siguiente declaración de una variable persona
Variable
persona: registro
nombre:cadena(20)
edad:entero
ocupación:cadena(25)
salario:real
fin registro
La descripción de este registro será:
Registro Persona
Identificador del
campo
Tipo del campo
Nombre
Edad
Ocupación
Salario
cadena(20)
entero
cadena(25)
real
Si quiero asignarle un valor al nombre, pondré:
persona.nombre ← ‘Juan Ignacio Perez’
Si quiero leer su salario, pondré
leer persona.salario
Los siguientes ejemplos ilustran cómo definir los tipos y cómo manipular la información de los campos:
Ejemplo1:
Tipos
TipoRegistro = registro
Campo1: TipoDato1
Campo2: TipoDato2
FinRegistro
Variables
VariableRegistro : TipoRegistro
variable1: TipoDato1
APUNTES TEÓRICOS
- 45 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
variable2: TipoDato2
Comienza
.....
.....
Leer(variable1)
Leer(variable2)
{ si queremos asignar los datos a los campos del registro hacemos }
VariableRegistro . Campo1 ← variable1
VariableRegistro . Campo2 ← variable2
......
Termina
No podríamos realizar las siguientes operaciones:
• Leer(VariableRegistro) { no se puede leer un registro completo}
• VariableRegistro . Campo1 ← variable2 { los tipos de datos no son iguales}
El tipo de los campos puede ser estructurado, por lo que su acceso depende de la estructura a la que
pertenece.
Veamos los siguientes ejemplos:
Tipos
TipoRegistroA = registro
CampoA1 TipoDato1
CampoA2: TipoDato2
FinRegistro
TipoRegistro = registro
Campo1: TipoRegistroA
Campo2: entero
FinRegistro
Variables
VariableRegistro : TipoRegistro
variable1: TipoDato1
variable2: TipoDato2
Comienza
........
{ para escribir el campo A1 de la variable VariableRegistro deberemos hacer}
Escribir (VariableRegistro . Campo1 . CampoA1)
........
Termina
Es necesario destacar que la elección de uso de cualquier estructura está directamente relacionada con el problema que estamos modelando y la información que queremos representar.
Podemos agrupar registros por medio de un arreglo, el cual puede ser de cualquier tipo simple
de datos (entero, real, caracter, etc. ) o tipos compuestos (registros. arreglos)
Teniendo en cuenta la declaración de tipo anterior y nuevas variables veremos como manipular
un arreglo de registros.
Tipos
TipoRegistro = registro
Campo1: TipoDato1
Campo2: TipoDato2
FinRegistro
Variables
VariableRegistro : TipoRegistro
ArregloRegistro: arreglo (30) de TipoRegistro
APUNTES TEÓRICOS
- 46 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Comienza
......
i ← 1 { quiero acceder a la posición 1 del arreglo }
VariableRegistro ← ArregloRegistro ( i ) { accedo a la información de un registro}
{ si ahora quiero mostrar el primer campo de la 5 posición del arreglo de registros}
Escribir (ArregloRegistro(5).Campo1)
......
Termina
Supongamos que queremos almacenar información del personal de la Facultad. Primero debemos definir qué estructura utilizaremos para contener la información. Una elección posible podría ser:
Tipos
RegistroPersona = Registro
Nombre
: cadena (20)
Edad
: entero
Ocupacion : cadena (25)
Salario
:real
FinRegistro
Variables
Yo : RegistroPersona
Facultad : Arreglo (30) de RegistroPersona { permite mantener información de
30 personas}
ARCHIVOS
Hasta aquí hemos manipulado datos (información) en variables de tipos de datos simples y
tipos estructurados. Estos tipos de variables se almacenan en memoria RAM, y por la volatilidad de la misma, no podemos mantener información permanentemente.
Introduciendo un nuevo tipo, el tipo archivo, podemos solucionar el problema de almacenamiento de información.
Una variable de tipo archivo se caracteriza por contener una secuencia de elementos de un tipo
base, que pueden ser registros o cualquier otro tipo simple. Así, cada elemento integrante de la secuencia
posee todas las propiedades y características de éstos.
Es conveniente destacar ahora los aspectos de manipulación lógica y física. El manejo lógico
es el que realizamos nosotros mediante programas que mantienen la información del archivo. El aspecto
físico es independiente de lo que nosotros realicemos en nuestros programas, ya que todos los sistemas
operativos donde se ejecutarán nuestros programas cuentan con una parte (el sistema de archivos) que se
encarga de operaciones transparentes para nosotros (tales como obtener espacio en disco o cinta para el
archivo, almacenar bit a bit, etc.).
El acceso a la información de un archivo puede hacerse en forma secuencial ó directa. Nosotros sólo utilizaremos el acceso secuencial, ya que lógicamente un archivo es una secuencia de registros y
no es recomendable violar esta propiedad. Tal vez no esté clara esta recomendación sobre la forma de acceso, pero se puede comprobar cuando se intenta modificar o detectar un error en un algoritmo.
Las características lógicas de un archivo que debemos destacar son:
1. Existe una posición actual del archivo. Ésto significa que cualquier operación que se realice a
un registro del archivo se materializará sobre el registro que es apuntado por esta posición actual.
2. El archivo posee una marca de fin-de-archivo, que nos permite identificar si hemos llegado al final.
Antes de enumerar las operaciones y los métodos que se aplican sobre archivos declaremos
un tipo archivo, un tipo registro, y las variables que necesitaremos para la descripción de los ejemplos:
Tipos
APUNTES TEÓRICOS
- 47 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
RegistroPersona = Registro
Nombre
: cadena (20)
Edad
: entero
Estado_Civil: carácter
Salario
:real
FinRegistro
ArchivoPersona = archivo de RegistroPersona
Variables
Profesor : RegistroPersona
Facultad : ArchivoPersona { permite mantener información del personal de la
Facultad}
Operaciones sobre archivos
⇒
ABRIR: Esta operación debe ser usada previamente a cualquier otra, para preparar la utilización del archivo.
Para Lectura: Esta operación se utiliza cuando el archivo ya está creado y se
desea acceder a la información que se encuentra en él.
Para Escritura: Esta operación se utiliza cuando el archivo no existe y se necesita crearlo para grabar información en él.
Es necesario aclarar el tipo de apertura del archivo.
Ejemplo
Abrir (Facultad ) {Para lectura} {se abre un archivo existente}
Abrir (Facultad) {Para escritura} { se abre un archivo que no existe}
⇒
CERRAR: Se utiliza esta operación siempre que se termina de procesar la información de un
archivo que ha sido abierto ya sea para lectura o para escritura.
Ejemplo
Cerrar (Facultad) {se cierra el archivo que se abrió previamente}
CUALQUIER ACCESO QUE SE PRETENDA REALIZAR SOBRE UN ARCHIVO CERRADO SERÁ NO
VÁLIDO
⇒
LEER: Se utiliza para leer el registro del archivo que se encuentra bajo el indicador de posición
actual descrito anteriormente. Esta lectura colocará el contenido de un registro del archivo en
una variable tipo registro que se deberá declarar para tal fin.
Es importante aclarar que con cada realización de la operación Leer, el indicador de posición actual se
irá modificando hasta avanzar hacia el fin-de-archivo.
Ejemplo
Leer(Facultad, Profesor) { coloca en la variable Profesor información de un registro
del archivo Facultad}
⇒
GRABAR: Se utiliza para agregar un registro en el archivo, colocando la información la variable
registro en un registro del archivo. Aclaramos que con cada operación Grabar que se realiza,
se irá modificando la marca de fin-de-archivo.
Ejemplo
Grabar(Facultad, Profesor) { agrega información de la variable profesor en el archivo Facul-
tad }
⇒
FIN: Es necesario utilizar esta operación para detectar el fin del archivo para saber si debemos
continuar procesando información de un archivo. Es operación devuelve un valor booleano, esto es verdadero o falso.
Ejemplo
APUNTES TEÓRICOS
- 48 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Fin(Facultad) { esta operación devolverá verdadero o falso, dependiendo de si el
indicador de posición actual esta sobre la marca de fin-de-archivo del
archivo Facultad}
Recursos para manipular archivos
Previo a describir los recursos para el uso de archivos debemos declarar algunas variables del
tipo estructurado que hemos visto con anterioridad. Estas (que se encuentran en memoria de acceso directo
obviamente) servirán para ordenar, realizar búsquedas sobre un archivo, etc.
El tipo estructurado que emplearemos es el arreglo unidimensional (un vector), donde cada
elemento de éste será un registro que contendrá la información de cada registro lógico del archivo que estemos procesando. Esta “duplicación de información” es necesaria para evitar realizar múltiples operaciones
Abrir y Cerrar sobre un archivo. También se hace para que el acceso a la información que se encuentra en
el archivo sea mas rápida, y nos permita realizar acceso directo a la misma, algo que ya dijimos que no es
recomendable en un archivo.
Tipos
RegistroPersona = Registro
Nombre
: cadena (20)
Edad
: entero
Estado_Civil : cadena (25)
Salario
:real
FinRegistro
ArchivoPersona = archivo de RegistroPersona { información en dispositivo de
almacenamiento secundario}
VectorPersona = arreglo (100) de RegistroPersona { información en memoria de
acceso directo}
Variables
Profesor : RegistroPersona
Facultad : ArchivoPersona { permite mantener información del personal de la Facultad}
InfoFacultad : VectorPersona
Bajar un archivo: la información de un archivo -existente en almacenamiento secundario (disco, cinta,
etc.)- se almacena en una variable del tipo estructurado.
Procedimiento BajarArchivo ( ref Facu : ArchivoPersona, ref InfoFacu : VectorPersona,
ref CantPersonas : entero )
Variables
Regi:RegistroPersona
I:entero
Comienza
I
0 { inicialmente suponemos que no existe información en el archivo}
Abrir (Facu) {Para lectura}
Mientras no Fin(Facu) Hacer
Comienza
I
I+1
Leer (Facu, Regi)
InfoFacu (I)
Regi { coloco en la posición I-esima del vector la información del registro leído}
Termina
CantPersonas
I { tenemos i-elementos en el vector de registros}
Cerrar (Facu)
Termina
APUNTES TEÓRICOS
- 49 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Subir un archivo: se graba la información desde memoria central en un archivo que se encuentra en almacenamiento secundario.
Procedimiento SubirArchivo( ref Facu : ArchivoPersona, InfoFacu : VectorPersona, CantPersonas : entero )
Variables
Regi:RegistroPersona
I:entero
Comienza
Abrir (Facu) {Para escritura}
Para I
1 hasta CantPersonas Hacer { coloco los i-elementos del vector en el archivo}
comienza
Regi ← InfoFacu (I )
Grabar (Facu, Regi ) { grabo el i-esimo elemento del vector en el archivo. Esta operación también modifica la marca fin-de-archivo }
termina
Cerrar ( Facu )
Termina
Considerando las anteriores aclaraciones y recomendaciones, procederemos a describir cuales son los
distintos procesos que se realizan sobre los archivos.
⌦ Apareo de archivos (mezclarlos respetando el orden).
Consiste en intercalar información de dos o más archivos, donde cada uno debe estar ordenado previamente en el mismo orden y bajo la misma clave.
Generalmente existe un archivo denominado Maestro y otro denominado Detalle, donde Detalle
es la actualización a la información que se encuentra en el Maestro.
⌦ ABM de archivos (Altas, Bajas y Modificaciones de información contenida en un archivo).
Los tipos de archivos que estamos estudiando son una fuente de información, y como tal, necesitamos mantenerla actualizada. La actualización implica agregar, borrar o modificar la información
que se encuentra en un registro.
⌦ Ordenamiento de un archivo, Búsqueda.
Para ordenar un archivo lo “bajamos” a memoria, a un vector de registros, lo ordenamos como se
ordena un vector de registros, y luego lo “subimos” a disco. Las búsquedas se pueden realizar
sobre el dispositivo, o más rápidamente en la memoria.
Cortes de Control
Desde los primeros algoritmos que hemos escrito, podemos observar que en alguna de sus
partes aparece una selección dicotómica que bifurca el proceso. Esa selección produce un corte en la secuencia, a partir de una condición que controla por cuál de las opciones debe seguir. Este corte de control
puede hacerse mediante una marca (bandera, flag, señal), o comparando variables de control. Por ejemplo, en la página 9 de este apunte, en el algoritmo que determina la mínima presión, se realiza un corte de
control en el condicional que testea el valor de marca. Veamos un ejemplo más complejo en el que se utiliza
más de un corte de control.
La empresa Argentina_Potencia cuenta con sucursales en diversas localidades del país, y dentro de ellas, cuenta con secciones. Cada empleado tiene su número de legajo. La información
por cada transacción realizada contiene:
Sucursal
Sección Legajo
Importe
El programa debe imprimir el total de cada empleado, de cada sección y de cada sucursal, y
finalizada la información, el total de la empresa. La información está ordenada por Sucursal,
Sección y Legajo.
Programa Totales
variables
APUNTES TEÓRICOS
- 50 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Sucursal, Sección, Legajo : cadena(3)
Importe: real
Suc_Ant, Sec_Ant, Leag_Ant : cadena(3)
Tot_Empre, Tot_Suc, Tot_Sec, Tot_Empleado: real
Comienza
Tot_Empre 0
Tot_Suc 0
Tot_Sec 0
leer (Sucursal, Sección, Legajo, Importe)
Suc_Ant
Sucursal
Sec_Ant Sección
Leag_Ant Legajo
Tot_Empleado
Importe
mensaje(Rta);
mientras Rta=’S’ hacer
comienza
leer (Sucursal, Sección, Legajo, Importe)
si Suc_Ant = Sucursal entonces { la sucursal es la misma y testeo la sección }
si Sec_Ant = Sección entonces { la sección es la misma y testeo el legajo }
si Leg_Ant = Legajo entonces {el empleado es el mismo y acumulo su importe }
Tot_Empleado
Tot_Empleado +Importe
sino { cambió el empleado. Acumulo en la
sección e imprimo el empleado }
comienza
Tot_Sec Tot_Sec + Tot_Empleado
escribir (Leg_Ant, Tot_Empleado)
Leag_Ant Legajo { defino legajo anterior }
Tot_Empleado
Importe
termina
sino {cambió la sección }
comienza
Tot_Sec Tot_Sec + Tot_Empleado { sumo a la sección
anterior }
Tot_Suc Tot_Suc + Tot_Sec { sumo a la sucursal }
escribirlinea (Leg_Ant, Tot_Empleado) {imprimo al empleado}
escribirlinea ( ‘total seccion ‘, Sec_Ant, ‘= ‘, Tot_Sec) { imprimo a la sección anterior }
Leg_Ant Legajo
Sec_Ant
Sección {defino legajo y sección anterior }
Tot_Empleado
Importe
Tot_Sec
0
termina
sino {cambió la sucursal }
comienza
Tot_Sec Tot_Sec + Tot_Empleado { sumo a la sección anterior }
Tot_Suc Tot_Suc + Tot_Sec {sumo a la sucursal }
Tot_Empre
Tot_Empre + Tot_Suc {sumo a la empresa }
escribirlinea (Leg_Ant, Tot_Empleado) {imprimo al empleado }
escribirlinea ( ‘total seccion ‘, Sec_Ant, ‘= ‘, Tot_Sec) { imprimo a la sección anterior }
escribirlinea ( ‘total sucursal ‘, Suc_Ant, ‘= ‘, Tot_Suc) {imprimo a la sucursal anterior }
Leag_Ant
Sec_Ant
Suc_Ant
Legajo
Sección
Sucursal {defino legajo , sección y sucursal anterior }
APUNTES TEÓRICOS
- 51 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
Tot_Empleado
Importe
Tot_Sec
0
Tot_Suc
0
termina
termina { termina el mientras Rta = ‘S’}
{ el operador indicó que no tiene más información, por lo que se debe imprimir todo lo correspondiente al último empleado, sección, sucursal y empresa }
Tot_Sec Tot_Sec + Tot_Empleado {sumo a la sección anterior }
Tot_Suc Tot_Suc + Tot_Sec {sumo a la sucursal }
Tot_Empre
Tot_Empre + Tot_Suc {sumo a la empresa }
escribirlinea (Leg_Ant, Tot_Empleado)
escribirlinea ( ‘total seccion ‘, Sec_Ant, ‘= ‘, Tot_Sec)
escribirlinea ( ‘total sucursal ‘, Suc_Ant, ‘= ‘, Tot_Suc)
escribirlinea ( ‘total empresa‘, Tot_Empre )
termina {Fin del Programa }
Las tres selecciones dicotómicas sombreadas son cortes de control. Todas y cada una determinan el estado del dato, lo que permite producir resultados y transformar las variables de control. Así es como podemos imprimir los datos de cada empleado, de cada sección dentro de una sucursal, y de cada sucursal dentro de la empresa.
Aplicación de cortes de control en Apareo de Archivos
El siguiente programa genera el archivo de una distribuidora, a partir de dos archivos de sendas sucursales.
Programa UNIFICACIÖN
tipos
regi_dato: registro
clave: entero;
cantidad: entero;
resto: algún tipo
fin registro
archi_datos: archivo de regi_dato;
variables
Distrib, Sucursal1, Sucursal2 : archi_datos
Procedimiento Apareo ( ref Distrib, Sucursal1, Sucursal2 : archi_datos);
var
regiSuc1, regiSuc2, regiDist: regi_dato;
comienza
abrir (Sucursal1) { para lectura}
abrir (Sucursal2) { para lectura}
abrir (Distrib) { para escritura}
si no fin(Sucursal1) ∧ no fin(Sucursal2) entonces {leo el primer registro de cada archivo}
comienza
leer(Sucursal1, regiSuc1)
leer(Sucursal2, regiSuc2)
termina
mientras no fin(Sucursal1) ∧ no fin(Sucursal2) hacer
comienza {este mientras lee y procesa info de los dos archivos mientras ambos tengan información}
si regiSuc1.clave = regiSuc2.clave entonces
comienza {se compone el registro resultante de la suma lógica de ambos}
regiDist.clave regiSuc1.clave
regiDist. cantidad regiSuc1.cantidad + regiSuc2.cantidad
regiDist. resto
regiSuc1.resto ⊕ regiSuc2.resto {suma
lógica}
grabar (Distrib, regiDist)
APUNTES TEÓRICOS
- 52 -
ALGORITMICA Y PROGRAMACIÓN
Elementos de Programación
leer(Sucursal1, regiSuc1)
leer(Sucursal2, regiSuc2)
termina
sino
si regiSuc1.clave < regiSuc2.clave entonces
comienza { genero el registro resultante con
la info del regiSuc1}
regiDist.clave regiSuc1.clave
regiDist. cantidad regiSuc1.cantidad
regiDist. resto
regiSuc1.resto
grabar (Distrib, regiDist)
leer(Sucursal1, regiSuc1)
termina
sino
comienza { genero el registro resultante con
la info del regiSuc2}
regiDist.clave regiSuc2.clave
regiDist. cantidad regiSuc2.cantidad
regiDist. resto
regiSuc2.resto
grabar (Distrib, regiDist)
leer(Sucursal2, regiSuc2)
termina
termina
{ por lo menos uno de los dos archivos se terminó}
mientras no fin(Sucursal1) hacer
comienza { no quedan datos de Sucursal2, y genero el registro resultante con la
info del regiSuc1}
regiDist.clave regiSuc1.clave
regiDist. cantidad regiSuc1.cantidad
regiDist. resto
regiSuc1.resto
grabar (Distrib, regiDist)
leer(Sucursal1, regiSuc1)
termina
mientras no fin(Sucursal2) hacer
comienza { no quedan datos de Sucursal1, y genero el registro resultante con la
info del regiSuc2}
regiDist.clave regiSuc2.clave
regiDist. cantidad regiSuc2.cantidad
regiDist. resto
regiSuc2.resto
grabar (Distrib, regiDist)
leer(Sucursal2, regiSuc2)
termina
cerrar (Sucursal1)
cerrar (Sucursal2)
cerrar (Distrib)
termina {fin procedimiento}
Comienza {programa principal}
{al comienzo del programa hay una serie de enunciados, los que preceden a la acción del apareo de archivos}
{precondición: Sucursal1 y Sucursal2 EXISTEN}
apareo(Sucursal1, Sucursal2, Distrib)
{ después del apareo, siguen otros enunciados que utilizarán el archivo Distrib}
termina {programa principal}
APUNTES TEÓRICOS
- 53 -
Descargar