Está en la página 1de 6

Programación Imperativa I

Algoritmos y Estructuras de Datos I


Segundo cuatrimestre de 2004

Aclaraciones: En los ejercicios donde se pide definir funciones o procedimientos se deben escribir las
precondiciones y postcondiciones de cada uno. Además hay que plantear los invariantes y las funciones
variantes en los casos que incluyan ciclos y realizar todas las demostraciones correspondientes.

Ejercicio 1. Dadas las siguientes funciones expresadas en lenguaje coloquial, indicar cuál es la precondición y
postcondición adecuada para cada una.
1. La función float raizEnesima(int n, int i), que recibe un número n y otro i y calcula la raı́z i-ésima
de n.
(a) {n = N 0 }
(b) {raizEnesima(I 0 , N 0 , ∆) ∧ j = 0}
(c) {True}
(d) {raizEnesima(I 0 , ∆0 , ∆)}
(e) {i = I 0 ∧ n = N 0 ∧ ∆ = ∆0 }
(f) {raizEnesima(I 0 , N 0 , ∆) ∧ i = 0}
(g) {i = I 0 ∧ n = N 0 ∧ I 0 > 0 ∧ (par (I 0 ) → N 0 ≥ 0)}
(h) {i = I 0 ∧ n = N 0 ∧ N 0 > 0 ∧ ∆ = ∆0 }
(i) {raizEnesima(I 0 , N 0 , ∆)}
donde raizEnesima(i, n : Z, r : Rl ) ≡ {r = n1/i } y par (x : Z) ≡ {x mod 2 = 0}.
2. La función int menorPrimoTresCifras(), que devuelve el menor número primo de tres cifras.
(a) {True}
(b) {i = I 0 ∧ n = N 0 ∧ (par (I 0 ) → N 0 ≥ 0)}
(c) {∆ = N 0 }
(d) {∆ = 101}
(e) {par (8)}
(f) {∆ ↔ menorPrimo3Cifras (101)}
donde menorPrimo3Cifras (x : Z) ≡ {x = 101}.

Ejercicio 2. Dada la función int producto(int n, int m) que devuelve el producto entre m y n, indicar:
1. ¿Cuál es la precondición adecuada para la función?

(a) P ≡ {n = N 0 ∧ m = M 0 }
(b) P ≡ {True}

2. ¿Cuál es la postcondición adecuada para la función?

(a) Q ≡ {∆ = m ∗ n}
(b) Q ≡ {∆ = M 0 ∗ N 0 }
(c) Q ≡ {True}

1
3. Suponiendo que la idea de implementación de la función es la siguiente:
Realizar un ciclo que sume el parámetro m tantas veces como lo indica el valor absoluto del
parámetro n.
Indicar cuáles son los PC , QC , I, B y F v que mejor se adecuan a la idea de este ciclo. Suponer una
precondición donde vale: n = N 0 ∧ m = M 0 .

(a) P c ≡ P
B ≡ {i ≤ abs (m)}
I ≡ {result = n ∗ i}
Fv = m − i
Qc ≡ Q

(b) P c ≡ {result = 0 ∧ i = 0 ∧ n = N 0 ∧ m = M 0 }
B ≡ {i < abs (n)}
I ≡ {result = m ∗ i ∧ 0 ≤ i ≤ abs (n) ∧ n = N 0 ∧ m = M 0 }
F v = abs (n) − i
Qc ≡ {result = abs (n) ∗ m ∧ n = N 0 ∧ m = M 0 }

(c) P c ≡ {result = 0 ∧ i = 0 ∧ n = N 0 ∧ m = M 0 }
B ≡ {i ≤ n}
I ≡ {result = m ∗ i ∧ 1 ≤ i ≤ n ∧ n = N 0 ∧ m = M 0 }
F v = abs (n − i)
Qc ≡ {result = n ∗ m}

donde abs(n : Z) ≡ {n ∗ β(n > 0) − n ∗ β(n ≤ 0)}.

4. Chequear que la opción elegida entre las de los puntos anteriores concuerdan con el siguiente código:

int producto(int n, int m) {


int i;
int result;
i = 0;
result = 0;
while (i < abs(n)) {
i = i + 1;
result = result + m;
}
if (n < 0){
result = -result;
}
return result;
}
}

int abs(int n) {
int result;
if (n > 0){
result = n;
}
else {
result = -n;
}
return result;
}

Escribir la precondición y postcondición adecuadas para la función abs.

2
Ejercicio 3. Escribir el código de las siguientes funciones respetando las especificaciones dadas.
1. int potencia(int n, int m)
P ≡ {n = N 0 ∧ m = M 0 ∧ (N 0 = 0 → M 0 6= 0) ∧ M 0 ≥ 0}
PC ≡ {i = 0 ∧ result = 1 ∧ P }
B ≡ {i < m}
I ≡ {result = ni ∧ 0 ≤ i ≤ m ∧ n = N 0 ∧ m = M 0 ∧ (N 0 = 0 → M 0 6= 0) ∧ M 0 ≥ 0}
Fv = m − i
0
QC ≡ {result = N 0M }
0
Q ≡ {∆ = N 0M }
2. int factorial(int n)
P ≡ {n = N 0 ∧ N 0 ≥ 0}
PC ≡ {i = 0 ∧ result = 1 ∧ P }
B ≡ {i < n}
I ≡ {result = fact (i) ∧ 0 ≤ i ≤ n ∧ n = N 0 ∧ N 0 ≥ 0}
Fv = n − i
QC ≡ {result = fact (N 0 )}
Q ≡ {∆ = fact (N 0 )}
Qn
donde fact(n : Z) ≡ { k=1 k}.

Ejercicio 4. 1. Determinar si la siguiente especificación concuerda con el código de programa dado. Justificar.
P ≡ {n = N 0 ∧ m = M 0 ∧ N 0 ≤ M 0 }
PC ≡ {i = n ∧ result ↔ False ∧ n = N 0 ∧ m = M 0 ∧ N 0 ≤ M 0 }
I ≡ {result ↔ (∃k : Z)(n ≤ k < i ∧ esCuadrado?(k)) ∧ n ≤ i ≤ m + 1 ∧ n = N 0 ∧ m = M 0 ∧ N 0 ≤ M 0 }
B ≡ {i ≤ m}
Fv = m − i
QC ≡ {result ↔ (∃k : Z)(N 0 ≤ k ≤ M 0 ∧ esCuadrado?(k))}
Q ≡ {∆ ↔ (∃k : Z)(N 0 ≤ k ≤ M 0 ∧ esCuadrado?(k))}
donde esCuadrado?(k : Z) ≡ {(∃j : Z)(j ∗ j = k)}.

bool hayAlgunCuadrado(int n, int m) {


int i;
int aux;
bool result;
if (m < n) {
aux = n;
n = m;
m = aux;
}
i = m;
result = false;
while (i > (n - 1)) {
result = result || cuadrado?(i);
i = i - 1;
}
return result;
}

Considerar la siguiente especificación para la función bool cuadrado?(int n):


∆ : B = cuadrado?(n : Z)
P ≡ {True}
Q ≡ {∆ ↔ (∃k : Z)(n = k ∗ k)}
2. En caso de no encontrar concordancia entre la especificación y el código, escribir un código que respete los
estados dados y enunciar los estados con los cuales se corresponde el código de programa descripto en el
punto anterior. En caso contrario, pensar otra manera de plantear y resolver el mismo problema.

3
Ejercicio 5. Dada la función int sumaMenores(int n, int m) cuya idea de implementación es la siguiente:
dados dos números naturales n y m, se devuelve la suma de todos los números naturales menores o iguales al
primero que son múltiplos del segundo. Por ejemplo:

sumaMenores(8, 2) = 0 + 2 + 4 + 6 + 8 = 20
sumaMenores(10, 3) = 0 + 3 + 6 + 9 = 18
sumaMenores(10, 12) = 0

Para ello se utiliza un ciclo que implementa la idea de la función. Decidir cuáles de los siguientes P , PC , I, F v,
B, QC y Q se adecuan a la idea de este ciclo y de esta función y cuáles no. Justificar en cada caso.
1. P ≡ {result = 0}
PC ≡ P
B ≡ {n > 0}
I ≡ {n ≥ 0 ∧ result = sumMenMul (N 0 , M 0 )}
Fv = n
QC ≡ {n = 0 ∧ result = sumMenMul (N 0 , M 0 )}
Q ≡ {n = 0 ∧ ∆ = sumMenMul (N 0 , M 0 )}
2. P ≡ {n = N 0 ∧ m = M 0 }
PC ≡ {result = 0}
B ≡ {n > 0}
I ≡ {n ≥ 0 ∧ result = sumMenMul (n, m)}
Fv = n
QC ≡ {n = 0 ∧ result = sumMenMul (n, m)}
Q ≡ {∆ = sumMenMul (N 0 , M 0 )}
3. P ≡ {n = N 0 ∧ m = M 0 }
PC ≡ {result = 0 ∧ m = M 0 }
B ≡ {n > 0}
I ≡ {n ≥ 0 ∧ (∀i : Z)(n ≤ i ≤ N 0 ∧ multiplo(i, M 0 ) → result = result + i) ∧ m = M 0 }
Fv = n
QC ≡ {n = 0 ∧ (∀i : Z)(0 ≤ i ≤ N 0 ∧ multiplo(i, M 0 ) → result = result + i) ∧ m = M 0 }
Q ≡ {(∀i : Z)(0 ≤ i ≤ N 0 ∧ multiplo(i, M 0 ) → ∆ = ∆ + i)}
4. P ≡ {n = N 0 ∧ m = M 0 }
PC ≡ {result = 0 ∧ m = M 0 ∧ n = N 0 }
B ≡ {n > 0}
I ≡ {n ≥ 0 ∧ result = (sumMenMul (N 0 , M 0 )) − (sumMenMul (n, M 0 )) ∧ m = M 0 }
Fv = n
QC ≡ {n = 0 ∧ result = sumMenMul (N 0 , M 0 ) ∧ m = M 0 }
Q ≡ {∆ = sumMenMul (N 0 , M 0 )}
donde
multiplo(n, m : Z) ≡ {(∃k :P
Z)(n = m ∗ k)} y
n
sumMenMul(n, m : Z) ≡ { i=0 i ∗ β(multiplo (i, m))}.

Ejercicio 6. Escribir la precondición y postcondición de los siguientes procedimientos, ası́ como su código:

1. El procedimiento void incrementar(int n ) que recibe un entero y le suma 1.
2. Un procedimiento que recibe dos enteros y los devuelve ordenados: el mayor en el primer parámetro y el
menor en el segundo.
3. Un procedimiento que recibe un entero; si éste es par lo divide por dos, y si es impar lo deja como está.

4. Un procedimiento que recibe tres enteros, los suma y al resultado lo multiplica por el primer entero. El
resultado final se guarda en el primer parámetro.

4
Ejercicio 7. Escribir la precondición, la postcondición y el código del procedimiento
↔ ↔
void divisionColateral(int n , int m ),
que dados dos enteros mayores que cero, los modifica asignándole al primero el resultado de la división entera
de n por m, y al segundo el resto de la división entera de n por m. En caso de utilizar un ciclo, especificar su
precondición y postcondición, guarda, invariante y función variante.

Ejercicio 8. Escribir el código de las siguientes funciones, respetando la especificación de estados dada. No
utilizar las funciones div y mod. Especificar los invariantes y las funciones variantes en los casos en los cuales
incluyan ciclos. En cada caso especificar la precondición y postcondición del ciclo y demostrar los siguientes
puntos:
• Vale el invariante antes de entrar al ciclo (PC → I)
• El cuerpo del ciclo preserva el invariante ({I ∧ B} S {I})
• La función variante es monótona decreciente y posee un cota inferior mayor o igual a cero.
• I ∧ ¬B → Q

1. int resto(int n, int m), que devuelve el resto de dividir n por m


P ≡ {n = N 0 ∧ m = M 0 ∧ M 0 6= 0}
Q ≡ {∆ = N 0 mod M 0 }
2. int divisionEntera(int n, int m), que devuelve el cociente de dividir n por m
P ≡ {n = N 0 ∧ m = M 0 ∧ M 0 6= 0}
Q ≡ {∆ = N 0 div M 0 }
3. int mcd(int n, int m), que devuelve el máximo común divisor entre n y m
P ≡ {n = N 0 ∧ m = M 0 }
Q ≡ {N 0 mod ∆ = 0 ∧ M 0 mod ∆ = 0 ∧ (∀x : Z)((N 0 mod x = 0 ∧ M 0 mod x = 0) → ∆ ≥ x)}
n

4. int numCombinatorio(int n, int m), que devuelve el numero combinatorio m
P ≡ {n = N 0 ∧ m = M 0 ∧ N 0 ≥ M 0 ∧ M 0 ≥ 0}
Q ≡ {∆ = fact(N 0 )/(fact(M 0 )fact(N 0 − M 0 ))}
donde fact es la función definida en el Ejercicio 3.
5. bool divisor(int n, int m), que determina si el primer parámetro divide al segundo
P ≡ {n = N 0 ∧ m = M 0 ∧ N 0 6= 0}
Q ≡ {∆ ↔ M 0 mod N 0 = 0}
6. bool cuadradoPerfecto(int n), que indica si n es un cuadrado perfecto
P ≡ {n = N 0 }
Q ≡ {∆ ↔ (∃x : Z)(N 0 = x ∗ x)}
7. int sumaDivisores(int n), que devuelve la suma de los divisores de n, si n 6= 0
P ≡ {n = N 0 ∧ N 0 6= 0}
Pabs(N 0 )
Q ≡ {∆ = i=1 i ∗ β(N 0 mod i = 0)}
donde abs es la función definida en el Ejercicio 2.
8. bool primo(int n), que indica si n es primo
P ≡ {n = N 0 ∧ N 0 > 0}
Q ≡ {∆ ↔ esPrimo(N 0 )}
donde esPrimo(x : Z) ≡ {(∀z : Z)(2 ≤ z < x → x mod z 6= 0)}.
9. int siguientePrimo(int n), que devuelve el primer primo mayor que n
P ≡ {n = N 0 }
Q ≡ {∆ ≥ N 0 ∧ esPrimo(∆) ∧ (∀x : Z)(N 0 ≤ x < ∆ → ¬esPrimo(x))}
10. int cantidadDePrimos(int n), que devuelve la cantidad de primos entre 0 y el parámetro
P ≡ {n = N 0 ∧ N 0 ≥ 0}
PN 0
Q ≡ {∆ = i=0 β(esPrimo(i))}

5
Ejercicio 9. Demostrar que se cumple la hipótesis del Teorema del Invariante en los procedimientos y funciones
de los Ejercicios 5 y 7.

Ejercicio 10. Dados los códigos de las siguientes funciones, decidir si cumplen o no las hipótesis del Teorema
del Invariante. En caso de no cumplirse las hipótesis, y cuando sea posible, reescribir el código de manera que sı́
se cumplan.
1. bool funcion1(int n) {
int i;
i = n;
while (true) {
if (primo(i)) {
return true;
}
else {
i = i + 1;
}
}
}
donde bool primo(int i) es la función especificada en el Ejercicio 8.8.
2. int funcion2(int n) {
int i;
int j;

i = n;
j = n+1;
while (mcdEuclides(j, i) == 1) {
j = j + 1;
}
return j;
}
donde ↔

int mcdEuclides(int a , int b ) {
int s;

if (a < b) {
s = a;
a = b;
b = s;
}
while (a != b) {
s = b;
b = mod(a, div(a, b));
a = s;
}
return a;
}

También podría gustarte