Metodolog´ıa de la Programación

Anuncio
Metodologı́a de la Programación
Septiembre de 2005
Ingenierı́a Técnica en Informática de Sistemas/ Ingenierı́a en Informática
Facultad de Informática de San Sebastián
SOLUCIÓN
1. (1 punto) Escribir una fórmula de primer orden que describa el siguiente estado de
computación: “En el array A(1..n) no hay dos elementos contiguos que sean iguales”
∀i(1 ≤ i < n → A(i) 6= A(i + 1))
2. (2.5 puntos) Documentar, con las aserciones que se marcan, el siguiente programa
que decide, en la variable booleana inverso, si el array A(1..n) es el inverso del
array B(1..n). Ejemplo: A(1..5) = (2, 5, 6, 8, 3) es el inverso de array B(1..5) =
(3, 8, 6, 5, 2).
(1) ≡ {n ≥ 1}
i := 0;
inverso := true;
(2) ≡ {0 ≤ i ≤ n ∧ (inverso ↔ ∀j(1 ≤ j ≤ i → A(j) = A(n − j + 1)))} E = n − i
while i < n and inverso loop
i := i + 1;
(3) ≡ {0 ≤ i ≤ n ∧ inverso ∧ ∀j(1 ≤ j < i → A(j) = A(n − j + 1))}
if A(i) 6= B(n − i + 1) then
(4) ≡ {0 ≤ i ≤ n ∧ ¬∀j(1 ≤ j ≤ i → A(j) = A(n − j + 1))}
inverso := false;
end if;
end loop
(5) ≡ {inverso ↔ ∀j(1 ≤ j ≤ n → A(j) = A(n − j + 1))}
3. (2.5 puntos) Derivar formalmente una iteración que decida si en un array A(1..n)
dado, cuyos elementos son enteros positivos, hay la misma cantidad de elementos
pares que de impares.
Pre≡ n ≥ 1 ∧ ∀k(1 ≤ k ≤ n → A(k) > 0)
Post≡ EquImP ar ↔ (2 ∗ N j(1 ≤ j ≤ n ∧ A(j)mod2 = 0) = n)
Inv≡ k = N j(1 ≤ j ≤ i ∧ A(j)mod2 = 0) ∧ 0 ≤ i ≤ n
E≡ n − k
INICIALIZACIÓN :
{n ≥ 1 ∧ ∀k(1 ≤ k ≤ n → A(k) > 0)} → {n ≥ 0}
i := 0; k := 0;
{k = N j(1 ≤ j ≤ i∧A(j)mod2 = 0) ∧ 0 ≤ i ≤ n}
FINALIZACIÓN : ¬B = i = n
Inv ∧ i = n → {k = N j(1 ≤ j ≤ n ∧ A(j)mod2 = 0)}
→ {(2 ∗ k = n) ↔ 2 ∗ N j(1 ≤ j ≤ n ∧ A(j)mod2 = 0) = n}
EquImP ar := (2 ∗ k = n)
{EquImP ar ↔ (2 ∗ N j(1 ≤ j ≤ n ∧ A(j)mod2 = 0) = n)}
CUERPO DE LA ITERACIÓN :
Inv∧i 6= n → {k = N j(1 ≤ j ≤ i∧A(j)mod2 = 0) ∧ 0 ≤ i < n}
E = n−i ∈ IN
i := i+1;
E decrece
{k = N j(1 ≤ j < i ∧ A(j)mod2 = 0) ∧ 0 ≤ i ≤ n} = ϕ
if A(i)mod2 = 0 then
{k + 1 = N j(1 ≤ j ≤ i ∧ A(j)mod2 = 0)}
k := k + 1;
[(ϕ ∧ A(i)mod2 6= 0) → Inv]
end if
Inv = {k = N j(1 ≤ j ≤ i ∧ A(j)mod2 = 0) ∧ 0 ≤ i ≤ n}
ITERACIÓN DOCUMENTADA :
{n ≥ 1 ∧ ∀k(1 ≤ k ≤ n → A(k) > 0)}
i := 0; k := 0;
{k = N j(1 ≤ j ≤ i ∧ A(j)mod2 = 0) ∧ 0 ≤ i ≤ n}
E =n−i
while i 6= n loop
{k = N j(1 ≤ j ≤ i ∧ A(j)mod2 = 0) ∧ 0 ≤ i < n}
i := i + 1;
{k = N j(1 ≤ j < i ∧ A(j)mod2 = 0) ∧ 0 ≤ i ≤ n} = ϕ
if A(i)mod2 = 0 then
{k + 1 = N j(1 ≤ j ≤ i ∧ A(j)mod2 = 0)}
k := k + 1;
[(ϕ ∧ A(i)mod2 6= 0) → Inv]
end if;
end loop;
{k = N j(1 ≤ j ≤ n ∧ A(j)mod2 = 0)}
EquImP ar := (2 ∗ k = n);
{EquImP ar ↔ (2 ∗ N j(1 ≤ j ≤ n ∧ A(j)mod2 = 0) = n)}
4. (2 puntos)
SÓLO SI HAS ELEGIDO EL APARTADO (a)
Especificar ecuacionalmente la función prefijo que, dadas una secuencia s y un
número natural n, devuelve la subsecuencia inicial de s con los n primeros elementos.
En caso de que s tenga menos de n elementos, la función devuelve s.
Ejemplo:
prefijo(< 4, 4, 2, 1, 1, 8 >, 3) =< 4, 4, 2 >
prefijo(< 4, 4, 2, 1, 1, 8 >, 9) =< 4, 4, 2, 1, 1, 8 >
sobre Secuencia(T ), Nat
operaciones prefijo : Secuencia(T ) × Nat → Secuencia(T )
ecuaciones
(1) prefijo(h i, n) = h i
(2) prefijo(x • s, n) =





hi
si n = 0
x • prefijo(s, n − 1) e.o.c.
SÓLO SI HAS ELEGIDO EL APARTADO (b)
La función duplicar : secuencia(T ) → secuencia(T ) tiene la siguiente especificación
ecuacional:
duplicar(h i) = h i
duplicar(t • s) = t • (t • duplicar(s))
Escribir un programa iterativo que implemente la función duplicar por medio del
método de Burstall.
Pre≡ T rue
Post≡ r1 = duplicar(s)
Inv≡ duplicar(s) = r1 @ duplicar(r2)
INICIALIZACIÓN : r1 := h i; r2 := s;
Justificación: duplicar(s) = h i @ duplicar(s)
FINALIZACIÓN :
(duplicar(s) = r1 @ duplicar(r2) ∧ es vacia(r2)) → r1 = duplicar(s)
Por tanto B = not es vacia(r2) y el resultado a devolver es r1
CUERPO DE LA ITERACIÓN (DESPLEGADO/PLEGADO):
duplicar(s) = r1 @ duplicar(r2) ∧ ¬es vacia(r2))
→ duplicar(s) = r1 @ duplicar(prim(r2)•resto(r2))
= r1 @ (prim(r2) • (prim(r2) • duplicar(resto(r2))))
= (r1 @ hprim(r2), prim(r2)i) @ duplicar(resto(r2))
= r10 @ duplicar(r20 )
Por tanto, (r10 , r20 ) = ((r1 @ hprim(r2), prim(r2)i), resto(r2))
FUNCIÓN DOCUMENTADA :
function duplicar it(s : Secuencia(T )) return r1 : Secuencia(T ) is
r2 : Secuencia(T );
{T rue}
r1 := h i; r2 := s;
{duplicar(s) = r1 @ duplicar(r2)}
while not es vacia(r2) loop
r1 := r1 @ hprim(r2), prim(r2)i;
r2 := resto(r2);
end loop;
{r1 = duplicar(s)}
5. (2 puntos) Verificar que la siguiente función recursiva calcula lo que su especificación
dice. Para ello, es imprescindible escribir previamente las hipótesis de inducción para
las dos llamadas internas.
function f rm (n : integer) return r : integer is
Pre ≡ {n ≥ 0}
if n = 0 then r := 0;
elsif n = 1 then r := 1;
else r1 := f rm(n − 1);
r2 := frm(n − 2);
r := (5 ∗ r1) − (6 ∗ r2);
end if;
Post ≡ {r = 3n − 2n }
CASOS SIMPLES:
{n ≥ 0 ∧ n = 0} → {0 = 3n − 2n }r := 0; {r = 3n − 2n }
{n > 0 ∧ n = 1} → {1 = 3n − 2n }r := 1; {r = 3n − 2n }
CASOS INDUCTIVOS:
Hipótesis de inducción: {n − 1 ≥ 0} r1 := frm(n − 1); {r1 = 3n−1 − 2n−1 }
{n − 2 ≥ 0} r2 := frm(n − 2); {r2 = 3n−2 − 2n−2 }
{n ≥ 0 ∧ n 6= 0 ∧ n 6= 1} → {n ≥ 2} → {n − 1 ≥ 0 ∧ n − 2 ≥ 0}
r1 := frm(n − 1); r2 := frm(n − 2);
{r1 = 3n−1 − 2n−1 ∧ r2 = 3n−2 − 2n−2 }
→ {(5∗r1)−(6∗r2) = 5∗3n−1 −5∗2n−1 −2∗3n−1 +3∗2n−1 = (5−2)∗3n−1 −(5−3)∗2n−1 = 3n −2n }
r := (5 ∗ r1) − (6 ∗ r2);
{r = 3n − 2n }
VALIDACIÓN DE LA INDUCCIÓN: En ambos casos simples, es obvio que
n ∈ IN. En el caso inductivo n ≥ 2, luego n−1, n−2 ∈ IN y ambos son estrictamente
menores que n.
Descargar