Examen II - LDC - Universidad Simón Bolívar

Anuncio
Universidad Simón Bolívar
Departamento de Computación y Tecnología de la Información
CI2611 – Algoritmos y Estructuras I
Septiembre-Diciembre 2009
Carnet:
Nombre:
Examen II
(40 puntos)
Antes de empezar, revise bien el examen, el cual consta de 4 (CUATRO) preguntas.
Pregunta 0
Pregunta 1
Pregunta 2
Pregunta 3
Total
15 puntos
10 puntos
5 puntos
10 puntos
40 puntos
Pregunta 0 - 15 puntos
Continuando con el estilo de las evaluaciones anteriores (el quiz y el examen I), se desea construir un programa que
realice un cierto análisis financiero a una serie de empresas.
Se trabajará con la información de p empresas, todas ellas pertenecientes a un mismo consorcio, lo cual significa
que las p empresas conforman colectivamente una gran macro-empresa. Como dato de entrada contaremos con la
ganancia o pérdida mensual de los últimos q meses de las p empresas en cuestión, información que vendrá dada en
una matriz v, esto es, un arreglo bidimensional, con p filas y q columnas. También se tendrá como otro dato de
entrada el capital y de todo el consorcio empresarial al inicio de esos q meses, esto es, el capital inicial de la gran
macro-empresa conformada por las p pequeñas empresas.
En cuanto al análisis a realizar, se debe determinar si para alguna de las p empresas su máxima ganancia en el
período de q meses dado fue exactamente igual a 0,4 % del capital inicial de todo el consorcio. Por otra parte, el
capital y de todo el consorcio debe ser actualizado a su valor final luego de los q meses en cuestión.
La especificación formal con la que debemos trabajar este problema algorítmico es la siguiente:
[[
const p , q : int ;
v : array [ 0..p ) × [ 0..q ) of real ;
var y : real ;
f : boolean ;
p>0 ∧ q>0 ∧ y=A
RealizarAnálisisFinancieroActualizandoCapital


 ( f ≡ ( ∃ i : 0 6 i < p : ( max j : 0 6 j < q : v[i][j] ) = 0,004 ∗ A ) ) 
∧
P


(y = A + (
i, j : 0 6 i < p ∧ 0 6 j < q : v[i][j] ) )
]]
Note que A es una variable de especificación y no una variable de programa.
En relación con el operador matemático max se tienen las dos siguientes observaciones: (i) debe ser considerado un
operador sin elemento neutro, por lo cual sus cuantificaciones no están bien definidas cuando el rango es vacío; y
(ii) sólo puede ser utilizado en especificaciones (aserciones) pero no en instrucciones del programa.
Se ha decidido además que su programa debe primero resolver el subproblema de determinar si alguna de las
empresas tuvo la máxima ganancia estipulada y calcular el balance acumulado de ganancias y pérdidas. Una vez
resuelto este subproblema se debe completar una solución al problema completo llamado RealizarAnálisisFinancieroActualizandoCapital.
La aserción intermedia correspondiente a resolver el primer subproblema es la siguiente, en la cual se hace referencia
a una nueva variable t de tipo real que debe ser declarada como parte del programa solución:
( f ≡ ( ∃ i : 0 6 i < p : ( max j : 0 6 j < q : v[i][j] ) = 0,004 ∗ A ) )
∧ P
(t = (
i, j : 0 6 i < p ∧ 0 6 j < q : v[i][j] ) ) .
Por último, este primer subproblema debe ser resuelto con una iteración diseñada según el siguiente invariante,
resultante de haber aplicado la técnica de reemplazo de una expresión constante por una nueva variable, que en este
caso hemos llamado k y es de tipo int:
06k6p
∧
( f ≡ ( ∃ i : 0 6 i < k : ( max j : 0 6 j < q : v[i][j] ) = 0,004 ∗ A ) )
∧ P
(t = (
i, j : 0 6 i < k ∧ 0 6 j < q : v[i][j] ) ) .
Construya entonces un programa que resuelva el problema RealizarAnálisisFinancieroActualizandoCapital
de acuerdo con las instrucciones dadas.
Para la iteración a construir con el invariante ya dado, indique también la cota variante de la iteración. Si su solución
requiere de otras iteraciones, indique también el invariante y la cota variante de ellas.
Nota: Su programa debe acoplarse a la solución parcial propuesta. La aserción intermedia dada y el invariante dado
deben ser respetados.
Otra nota: No puede utilizar recursión.
Pregunta 1 - 10 puntos
Se desea utilizar recursión para construir un programa que imprima los dígitos decimales de un entero no-negativo.
La secuencia completa de dígitos deberá ser impresa entre llaves angulares (“h” y “i”), los dígitos deberán ser impresos
separados por comas (“,”-s), y el orden de impresión de los dígitos deberá ser en orden decreciente de significación.
Por ejemplo: si la entrada es el entero 2009, la salida a imprimir será el string “h2, 0, 0, 9i”, y si la entrada es el
entero 715, la salida a imprimir será el string “h7, 1, 5i”. Note el orden decreciente de significación de los dígitos en
ambos casos, lo cual quiere decir que el primer dígito impreso fue el más significativo, 2 en el caso de 2009 y 7 en
el caso de 715, y el último dígito impreso fue el menos significativo, 9 en el caso de 2009 y 5 en el caso de 715.
Debe evitarse imprimir dígitos no-significativos, por lo que secuencias de ceros en el extremo izquierdo no deben
aparecer en la salida. Por ejemplo: para la entrada 2009, no se debe imprimir “h0, 0, 0, 2, 0, 0, 9i” ni “h0, 2, 0, 0, 9i”.
La única excepción en la que un cero será impreso en el extremo izquierdo de la secuencia de salida es cuando el
entero de entrada sea el entero 0, en cuyo caso la salida deberá ser la secuencia unitaria “h0i”. Esto es, para el entero
de entrada 0 consideraremos al dígito cero como su (único) dígito significativo.
De esta manera, las secuencias de dígitos decimales de salida nunca son vacías, nunca empiezan por cero para
entradas estrictamente positivas, y son únicas para cada posible entrada.
La especificación del programa a construir es la siguiente:
[[
const n : int ;
n>0
ImprimirSecuenciaDígitosDecimales
En la salida se encuentra impresa la secuencia no-vacía de dígitos decimales significativos de n,
en orden decreciente de significación, separados por “,”-s y con un “h” al inicio y un “i” al final.
]]
Para resolver el problema, se ha decidido que Ud. debe apoyarse en un procedimiento auxiliar recursivo con la
siguiente especificación:
proc imprimirDigs ( in x : int )
Pre : x > 0
Post : En la salida se encuentra impresa la secuencia no-vacía de dígitos decimales significativos de x,
en orden decreciente de significación y separados por “,”-s.
Note las diferencias entre la especificación de este procedimiento auxiliar y la especificación del problema original
completo: (i) el procedimiento no acepta al cero como entrada mientras el problema original sí, y (ii) el procedimiento
no debe imprimir las llaves angulares mientras que en el problema original éstas sí deben ser impresas.
Construya entonces un procedimiento recursivo que satisfaga la especificación dada para imprimirDigs, indicando
la cota variante correspondiente que asegure terminación, y luego construya un programa principal que resuelva el
problema original ImprimirSecuenciaDígitosDecimales haciendo uso de este procedimiento.
Para realizar la impresión, suponga que cuenta con dos procedimientos ya construidos printStr y printInt que
permiten imprimir, respectivamente, un string dado o un entero dado. Esto es, la llamada printStr (s) imprime
el string s y la llamada printInt (a) imprime el entero a. Por ejemplo: printStr (“h”) imprime una llave angular
izquierda, esto es, imprime el string “h”, y printInt (25) imprime el entero 25, esto es, imprime el string “25”.
Nota: Su procedimiento y su programa deben acoplarse a las especificaciones dadas. Además, no puede utilizar
estructuras de datos auxiliares, esto es, arreglos auxiliares.
Otra nota: No puede utilizar iteración.
Pregunta 2 - 5 puntos
Teniendo como contexto a la siguiente declaración de variables
var p , q , n : int ;
v : array [ 0..n ) of real ;
demuestre la tripleta de Hoare
0 6 p < n ∧ 0 6 q < n ∧ v[p] 6 v[q]
v[p] 6 v[q]
v[p] := (v[p] + v[q]) / 2
.
Pregunta 3 - 10 puntos
Suponga que se cuenta con un procedimiento ya construido cuyo encabezado es
proc
calcularLogaritmo (in a, b : int ; out c : real )
Pre : a > 2 ∧ b > 1
Post : c = loga b
,
el cual Ud. puede utilizar para resolver el siguiente problema:
[[
const p , q : int ;
var y : real ;
26p6q
CalcularExpresiónInteresante
Q
y = ( i : p 6 i < q : logi (i + 7) )
]]
.
Se tiene además la siguiente solución parcial al problema CalcularExpresiónInteresante:
[[ var k : int ;
y, k := ? , ?
(
)
Q
Invariante : 2 6 p 6 k 6 q ∧ y = ( i : k 6 i < q : logi (i + 7) )
Cota variante :
; do k 6= ?
?
→ [[ var tmp : real ;
k := ?
; ?
; y := ?
]]
od
]]
Ud. debe completar este programa rellenando las incógnitas ? , y realizar sólo una parte de la demostración de
correctitud de su programa, según se indica a continuación:
(a) Rellene las incógnitas ? de forma tal que el resultado sea una solución correcta.
(b) De acuerdo con las condiciones que deben cumplirse según el Teorema de Invariancia para que la solución
dada sea correcta, demuestre (sólo) que el cuerpo de la iteración mantiene el invariante.
Nota: No puede cambiar nada de la solución parcial propuesta, excepto rellenar las incógnitas.
Otra nota: El procedimiento calcularLogaritmo ya está previamente construido y se sabe que funciona correctamente.
Descargar