Fundamentos de Programação Solução do Segundo Teste 23 de Janeiro de 2012 09:00 10:30 Nome: Número: 1. (1.0) Explique em que consiste a abstracção de dados, usando os termos barreiras de abstracção, encapsulação da informação e anonimato da representação. A abstracção de dados consiste em separar a o modo como os dados são utilizados do modo como os dados são representados. Para isso definem-se camadas conceptuais lidando com cada um destes aspectos estando estas camadas separadas por "barreiras de abstracção" que definem o modo como os programas acima da barreira podem comunicar com os programas que se encontram abaixo da barreira. Idealmente, os programas que se encontram a um dado nível de abstracção contêm toda a informação necessária para lidar com um certo tipo de dados, a informação está encapsulada" dentro desta camada conceptual, e escondem das restantes partes do programa o modo como a informação está representada, o que é conhecido por anonimato da representação". 2. (1.0) Diga quais são as vantagens e os inconvenientes da programação imperativa. A vantagem da programação imperativa corresponde ao facto de esta permitir lidar com entidades que mudam ao longo do tempo. Por outro lado, a programação imperativa funciona através de efeitos o que pode esconder certas acções realizadas pelo programa e podendo afectar outras partes do programa. 3. (1.0) Diga quais são as fases por que passa o desenvolvimento de um programa e o que se faz em cada uma delas. (a) Análise do Problema. Determina exactamente o que tem de ser feito. (b) Desenvolvimento da Solução. Determina-se como deve ser feito, através do desenvolvimento de um algoritmo. (c) Programação da Solução. Corresponde à escrita do algoritmo desenvolvido recorrendo a uma linguagem de programação. (d) Testes. Corresponde a verificar se todos os programas em conjunto correspondem à solução desejada
Número: Pág. 2 de 7 (e) Manutenção. Consiste na verificação da possibilidade de alterações nas especificações do problema, e, no caso de alteração de especificações, na alteração correspondente do programa e na correcção dos eventuais erros descobertos durante o funcionamento do programa. 4. (1.0) O que é um enquadramento? Qual a restrição que lhe é imposta? Um enquadramento é constituído por um conjunto (possivelmente vazio) de ligações. Uma ligação associa um nome a um valor. Num enquadramento não podem existir duas ligações distintas para o mesmo nome. 5. (1.0) Diga o que é um ponteiro. Qual a característica que distingue um ponteiro dos outros tipos de informação? Um ponteiro é qualquer coisa que aponta. Ao passo que com a utilização de outros tipos de informação, estamos fundamentalmente interessados no valor da entidade, com ponteiros, não estamos interessados no valor do ponteiro, mas sim no valor para onde ele aponta. 6. (1.5) Usando a abstracção adequada, escreva o procedimento intercala que recebe duas listas, e devolve a lista que resulta de intercalar os elementos das duas listas. Se as listas não forem do mesmo tamanho, o que restar da lista maior deverá ser adicionado no fim. > (intercala (3 2 4) ( 3)) (3 2 4 3) > (intercala (2 3) (4 5 8 6)) (2 4 3 5 8 6) (define (intercala lst1 lst2) (cond ((lista-vazia? lst1) lst2) ((lista-vazia? lst2) lst1) (else (insere (primeiro lst1) (insere (primeiro lst2) (intercala (resto lst1) (resto lst2))))))) 7. Escreva um procedimento chamado conta-pares que recebe uma lista de números inteiros, e devolve o número de elementos da lista que correspondem a números pares. Por exemplo, > (conta-pares (4 5 6)) 2 > (conta-pares (3 5 7)) 0 (a) (1.5) Utilizando programação funcional e não recorrendo a procedimentos de ordem superior. Utilize a abstracção adequada.
Número: Pág. 3 de 7 (define (conta-pares lst) (cond ((lista-vazia? lst) 0) ((even? (primeiro lst)) (+ 1 (conta-pares (resto lst)))) (else (conta-pares (resto lst))))) (b) (1.0) Utilizando programação funcional e recorrendo aos procedimentos de ordem superior (funcionais sobre listas) filtra, transforma e acumula. (define (conta-pares lst) (acumula + (transforma (lambda (x) 1) (filtra even? lst)))) 8. (1.5) Considere o algoritmo de Euclides para calcular o máximo divisor comum entre dois inteiros: (1) o máximo divisor comum entre um número e zero é o próprio número; (2) quando dividimos um número por um menor, o máximo divisor comum entre o resto da divisão e o divisor é o mesmo que o máximo divisor comum entre o dividendo e o divisor. Usando programação imperativa e o ciclo apropriado, escreva um procedimento chamado mdc para calcular o máximo divisor comum entre dois números utilizando o algoritmo de Euclides. (define (mdc m n) (let ((aux 0)) (while (not (= n 0)) (set! aux n) (set! n (remainder m n)) (set! m aux)) m)) 9. (1.5) Usando o ciclo adequado, escreva um procedimento chamado algum-satisfaz-lista? que recebe uma lista e um predicado e devolve verdadeiro se algum dos elementos da lista satisfizer o predicado e falso em caso contrário. > (algum-satisfaz-lista? (0 3 4 5) even?) #t > (algum-satisfaz-lista? (0 3 4 5) (lambda (x) (> x 10))) #f (define (algum-satisfaz-lista? lst pred) (while (and (not (lista-vazia? lst)) (not (pred (primeiro lst)))) (set! lst (resto lst))) (not (lista-vazia? lst))) 10. (1.5) Escreva um procedimento chamado junta-vectores que recebe dois vectores, e devolve um novo vector que resulta de juntar o segundo vector ao final do primeiro.
Número: Pág. 4 de 7 > (junta-vectores (vector 3 2 4) (vector 3)) #(3 2 4 3) > (junta-vectores (vector) (vector 4 5 3)) #(4 5 3) (define (junta-vectores v1 v2) (let* ((comp1 (vector-length v1)) (comp2 (vector-length v2)) (novo (make-vector (+ comp1 comp2)))) (dotimes (i comp1) (vector-set! novo i (vector-ref v1 i))) (dotimes (i comp2) (vector-set! novo (+ i comp1) (vector-ref v2 i))) novo)) 11. Um acumulador é um procedimento que é chamado repetidamente com apenas um argumento numérico e acumula os seus argumentos numa soma. De cada vez que é chamado, retorna a soma acumulada até ao momento. O procedimento faz-acumulador gera acumuladores, cada um dos quais mantendo uma soma independente. O valor de entrada para o procedimento faz-acumulador deve especificar o valor inicial da soma. Por exemplo, > (define a (faz-acumulador 5)) > (a 10) 15 > (a 10) 25 (a) (1.5) Escreva o procedimento faz-acumulador. (define (faz-acumulador valor) (lambda (inc) (set! valor (+ valor inc)) valor)) (b) (1.5) Desenhe o diagrama de ambientes criado pela interacção acima.
Número: Pág. 5 de 7 Ambiente Global faz-acumulador: a: valor: 5 15 25 E1 parâmetros: valor corpo: (lambda (inc) (set! valor (+ valor inc)) valor) parâmetros: inc corpo: (set! valor (+ valor inc)) valor inc: 10 E2 inc: 10 E3 12. Considere a seguinte interacção em Scheme: > (define (mcons 1 (mcons 2 null))) > (define (mcons 1 (mcons 2 null))) > (define (mcons 5 (mcdr ))) > (set-mcar! 5) (a) (1.0) Represente as estruturas resultantes. > (define (mcons 1 (mcons 2 null))) > (define (mcons 1 (mcons 2 null)))
Número: Pág. 6 de 7 > (define (mcons 5 (mcdr ))) 5 > (set-mcar! 5) 5 5 2 (b) (1.0) Durante a avaliação das suas formas houve a criação de lixo? Justifique a sua resposta. Foi criado lixo correspondente aos pares a cinzento, visto estes não poderem ser acedidos de nenhuma das estruturas. 5 5 2 13. (1.5) Escreva um procedimento chamado rasto que recebe uma cadeia de caracteres correspondendo ao nome de um procedimento, e um procedimento de um argumento. O procedimento rasto devolve um procedimento de um argumento que escreve no écran (usando o procedimento primitivo display) a indicação de que o procedimento foi avaliado e o valor do seu argumento, escreve também o resultado do procedimento, e devolve o valor de aplicar o procedimento original ao argumento recebido. Por exemplo, partindo do princípio que o procedimento quadrado foi definido, podemos gerar a seguinte interacção:
Número: Pág. 7 de 7 > (define rasto-quadrado (rasto "quadrado" quadrado)) > (rasto-quadrado 4) Avaliação de quadrado, com o argumento 4 Resultado 16 16 > (define (rasto nome proc) (lambda (x) (display "Avaliação de ") (display nome) (display ", com o argumento ") (display x) (newline) (let ((valor (proc x))) (display "Resultado ") (display valor) (newline) valor)))