Ana Cardoso Cachopo Ano Lectivo 1998/1999 -...

73
Aulas práticas da cadeira de Introdução à Programação Ana Cardoso Cachopo Ano Lectivo 1998/1999

Transcript of Ana Cardoso Cachopo Ano Lectivo 1998/1999 -...

Page 1: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

Aulas práticas da cadeira deIntrodução à Programação

Ana Cardoso Cachopo

Ano Lectivo 1998/1999

Page 2: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

CONTEÚDO 1

Conteúdo

1 Apresentação 2

2 Os elementos da programação 3

3 Introdução ao UNIX, emacs, mail, news e www 8

4 Recursão 13

5 Processos iterativos vs recursivosRecursão em árvores 19

6 Ordens de crescimentoProcedimentos de ordem superior 23

7 Métodos gerais: procedimentos que retornam procedimentos 31

8 Abstracção de dadosPares em Scheme 36

9 Listas em Scheme 46

10 Listas em árvore em Scheme 53

11 Mais exercícios sobre listas 58

12 Quote 64

13 Modularidade, objectos e estado 68

Page 3: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

1 APRESENTAÇÃO 2

1 Apresentação

Sumário

• Esta aula vai servir para nos conhecermos melhor . . .

• Eu

– Nome

– Entrei para a LEIC no primeiro ano em que ele existiu

– Escolhi o ramo de Inteligência Artificial

– Dou aulas desde o 4oano no Grupo de Inteligência Artificial do IST.Ver http://www.gia.ist.utl.pt

• Eles

– Estão na primeira opção? Se não, quais eram as primeiras?

– Quais as expectativas em relação ao curso e à cadeira em particular?

– Vêm de Lisboa? Se não, de onde vêm, onde vivem?

– Vêm da via geral ou tecnológica?

– Sabem programar? Em que linguagem?

– São repetentes? A cadeira está muito diferente, têm que vir às aulas.

• IP

– Ensinamosprogramação, não Scheme

– Porquê Scheme (linguagem simples mas poderosa)

– A cadeira e o curso não são difíceis, mas dão muito trabalho. Énecessário trabalhare experimentar os programas em computador

– É necessário fazer inscrição nas turmas, de acordo com a turma atribuida pelo SOP

– É necessário trazer uma fotografia na próxima semana para o verbete

– Devem pedir área nocamoes . Na biblioteca da LEIC, custa 1000$00 e uma foto-grafia

– Página da cadeira:http://www.gia.ist.utl.pt/cadeiras/ip

– Grupo de newsist.cadeiras.leic.ip

– Endereço de correio electró[email protected]

Page 4: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

2 OS ELEMENTOS DA PROGRAMAÇÃO 3

2 Os elementos da programação

Sumário O objectivo desta aula é que os alunos aprendam a utilizar o Scheme e a construirprocedimentos simples.

Resumo

Page 5: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

2 OS ELEMENTOS DA PROGRAMAÇÃO 4

Exercícios

Exercício 2.1(Livro — 1.1) Em baixo é apresentada uma sequência de expressões. Diga qual é o resultadoimpresso pelo interpretador de Scheme quando é avaliada cada uma dessas expressões. Assumaque a sequência é avaliada pela ordem apresentada.

10

(+ 5 3 4)

(- 9 1)

(/ 6 2)

(+ ( * 2 4) (- 4 6))

(define a 3)

(define b (+ a 1))

(+ a b ( * a b))

(= a b)

(if (and (> b a) (< b ( * a b)))ba)

(cond ((= a 4) 6)((= b 4) (+ 6 7 a))(else 25))

(+ 2 (if (> b a) b a))

( * (cond ((> a b) a)((< a b) b)(else -1))

(+ a 1))

Resposta:

> 1010

> (+ 5 3 4)12

Page 6: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

2 OS ELEMENTOS DA PROGRAMAÇÃO 5

> (- 9 1)8

> (/ 6 2)3

> (+ ( * 2 4) (- 4 6))6

> (define a 3)

> (define b (+ a 1))

> (+ a b ( * a b))19

> (= a b)#f

> (if (and (> b a) (< b ( * a b)))ba)

4

> (cond ((= a 4) 6)((= b 4) (+ 6 7 a))(else 25))

16

> (+ 2 (if (> b a) b a))6

> ( * (cond ((> a b) a)((< a b) b)(else -1))

(+ a 1))16

Exercício 2.2(Livro — 1.2) Traduza a seguinte expressão para a notação prefixa:5+4+(2−(3−(6+ 4

5)))

3(6−2)(2−7)

Resposta:

(/ (+ 54(- 2

(- 3(+ 6 (/ 4 5)))))

( * 3(- 6 2)

Page 7: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

2 OS ELEMENTOS DA PROGRAMAÇÃO 6

(- 2 7)))

O que dá

-37/150

Se algum dos números fosse um real, o resultado seria

-0.24666666666667

Exercício 2.3Defina um procedimento que calcula o volume de uma esferav = 4

3πr3.

Resposta:

(define (volume raio)( * (/ 4 3)

pi(cubo raio)))

(define (cubo x)( * x x x))

(define pi 3.1415927)

Exercício 2.4(Livro — 1.3) Defina um procedimento que recebe três números como argumentos e devolve asoma dos quadrados dos dois maiores.Resposta:

(define (square a)( * a a))

(define (sum-of-squares a b)(+ (square a) (square b)))

(define (largest a b c)(cond ((and (>= a b) (>= a c)) a)

((and (>= b a) (>= b c)) b)(else c)))

Precisa de>= porque, se tiver só> e os argumentos forem4, 4 e3, não funciona.

(define (largest2 a b c)(if (> a b)

(if (> a c)ac) ; nao pode ser o b pq a ja’ e’ maior

(if (> b c)bc)))

Page 8: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

2 OS ELEMENTOS DA PROGRAMAÇÃO 7

(define (max a b)(if (> a b)

ab))

(define (largest3 a b c)(max a (max b c)))

(define (second-largest a b c)(if (> a b)

(if (> b c)b(if (> a c)

ca))

(if (> a c)a(if (> b c)

cb))))

(define (sum-of-squares-of-larger-two a b c)(sum-of-squares (largest a b c) (second-largest a b c)))

Page 9: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

3 INTRODUÇÃO AO UNIX, EMACS, MAIL, NEWS E WWW 8

3 Introdução ao UNIX, emacs, mail, news e www

Sumário O objectivo desta aula é que os alunos aprendam os rudimentossobre a utilização dosistema operativo UNIX, bem como a utilização do editor de texto emacs, que pode tambémservir para ler mail e news.A primeira metade deve ser passada numa sala normal (com quadro) e deve ser apresentado omodo de interagir com o sistema operativo, o conceito de ficheiro, directoria e os rudimentos deedição de texto.

Resumo

• Características do sistema operativo Unix

– Sistema multi-utilizador e multi-tarefa

– Conceitos essenciais: programas, ficheiros, processos

– Sistema de ficheiros hierárquico (nomes de ficheiros desde a raiz do disco)

• O utilizador

– É reconhecido pelo sistema através do seu ´username´ e tem a sua ´password´

– Pertence a um grupo de utilizadores

– Tem um espaço reservado em disco (quota)

– Está (?) protegido de outros utilizadores

– Tem um ambiente personalizado

• Entrar no sistema

Rede das Novas Licenciaturas

login: ic-ipPassword:Last login:Mon Sep 29 18:41:32 from marte.gia.ist.utl.pt

Bem-vindo ‘a Rede das Novas Licenciaturas

[...]

There are No news.6:52pm up 3 day(s), 23:40, 91 users, load average: 7.80, 6.79 , 6.27

ic-ip@camoes[~]#101

• Alterar a password

ic-ip@camoes[~]#101 passwdpasswd: Changing password for ic-ipEnter login password:New password:Password is too short - must be at least 6 characters.New password:Password must contain at least two alphabetic characters an d

Page 10: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

3 INTRODUÇÃO AO UNIX, EMACS, MAIL, NEWS E WWW 9

at least one numeric or special character.New password:Re-enter new password:

• Sair do sistema

ic-ip@camoes[~]#102 logoutic-ip@camoes logged out at Mon Sep 29 18:53:24 WET DST 1997

• Sintaxe dos comandos em UNIXcomando [-opção * ] [argumento * ]As opções especificam uma forma particular de executar o comando.Os argumentos especificam informação sobre a qual o comando vai operar.

• Manipular directoriaspwd Mostra a directoria correntemkdir nomeDir Cria uma directoria chamadanomeDirrmdir nomeDir Remove a directorianomeDir , se estiver vaziacd [nomeDir] Muda para a directorianomeDirls Lista os ficheiros da directoria corrente

• Manipular ficheiros

cp nomeFichVelho nomeFichNovoCopianomeFichVelho paranomeFichNovo

cp nomeFich* nomeDirCopia um conjunto de ficheiros para a directorianomeDir

mv nomeFichVelho nomeFichNovoMuda o nome denomeFichVelho paranomeFichNovo

mv nomeFich* nomeDirMove um conjunto de ficheiros paranomeDir

mv nomeDirVelho nomeDirNovoMove uma estrutura de directorias para outra directoria

rm nomeFich*Apaga um conjunto de ficheiros

• Visualizar o conteúdo de ficheiros

cat nomeFich*Lê caracteres do dispositivo de entrada standard ou de uma lista de ficheiros e mostra essescaracteres no dispositivo de saída standard

more nomeFich*Mostra o conteúdo de um conjunto de ficheiros, página a página

head -n nomeFich*Mostra as primeirasn linhas de um conjunto de ficheiros

tail -n nomeFich*Mostra as últimasn linhas de um conjunto de ficheiros

• Imprimir ficheiros

Page 11: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

3 INTRODUÇÃO AO UNIX, EMACS, MAIL, NEWS E WWW 10

lpr [-P impressora] nomeFich*Imprime os ficheiros naimpressora

lpq [-P impressora] job* userId*Escreve o ´status´ dos ´jobs´ especificados e/ou dos ´jobs´ dos utilizadores especificados queestão naimpressora

lprm [-P impressora] job* userId*Cancela todos os ´jobs´ especificados e/ou os ´jobs´ dos utilizadores especificados que estãona impressora

• Mudar as permissões de um ficheiro

ls -l nomeFichPara ver quais são as permissões de um ficheiro

chmod -R mudanca [, mudanca]* [nomefich]+Para mudar as permissões de ficheiros, ondemudanca é da forma: SujeitoSinalValorSujeito u, g, o, aSinal +, -, =Valor r, w, x

Exemplo:chmod u+rwx,go-rwx fich

umask [modo]Para mudar as permissões por omissão para os ficheiros e directorias criados, ondemodo éum número em octal

• Para mais informações acerca de comandos e utilitários UNIX

man palavraMostra (com omore ) as páginas do manual associadas apalavra

man -k palavraMostra as entradas do manual que contêmpalavraExemplos:man -k mode , man chmod

• Utilização do Mail

mailx enderecoEnvia uma mensagem paraendereco a partir da ´shell´ do UNIX.ctrl-d significa end-of-file

mailx [-f nomeFich] [endereco]*Envia o ficheironomeFich paraendereco

mailxServe para ler o correio da área do utilizador.? dá ajuda sobre os vários comandos existentes

• Caracteres especiais importantesctrl-d End-Of-File - indica o fim de um ficheiroctrl-c Interrupt - termina o processo que está a ser executadoctrl-z Suspend - suspende o processo que está a ser executado

Page 12: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

3 INTRODUÇÃO AO UNIX, EMACS, MAIL, NEWS E WWW 11

• Redirecionamento de entrada e saída

< nomeFichredirecciona o dispositivo de entrada standard para nomeFich Permite usar o conteúdo de umficheiro como entrada para um processo

> nomeFich redirecciona o dispositivo de saída standard para nomeFichPermite guardar o re-sultado de um processo num ficheiro

• Internet

ist.cadeiras.leic.ipNews — grupos de discussão de assuntos de interesse para a cadeira, exercicios, avisos im-portantes, etc (emacs,tin , pine )

http://www.gia.ist.utl.pt/cadeiras/ipWWW — página da cadeira de IP (lynx , netscape , internet explorer )

• Manipular processosps Mostra os processos do utilizadorkill numProcesso Mata processos do utilizadorbg [numProcesso] Passa um processo do utilizador para ´background´fg [numProcesso] Passa um processo do utilizador para ´foreground´& Executa um processo do utilizador em ´background´

• No camoes

setenv DISPLAY xxx:0Ondexxx é o endereço IP da máquina na janela inicial (só para terminais gráficos)

emacs -font fixedPode ser necessário se tiverem problemas com as fontes, por não estarem instaladas no sis-tema

• O emacsO emacs é um editor de texto.

Tem extensões para escrever código em várias linguagens de programação, ler mail e news, entreoutras.

O emacs tem ajuda e documentação disponível no menu Help, que pode ser utilizada para aprendera trabalhar com ele.

Page 13: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

3 INTRODUÇÃO AO UNIX, EMACS, MAIL, NEWS E WWW 12

Exercícios

Exercício 3.1Escreva em Scheme os seguintes procedimentos:

• Um procedimento chamadohipotenusa que, dados os comprimentos dos dois catetosde um triângulo rectângulo, calcula o comprimento da hipotenusa. Dados os comprimentosdos catetosa e b do triângulo, a hipotenusah é calculada como:h =

√a2 + b2

• Um procedimento chamadoperimetro que, dados os comprimentos dos dois catetos deum triângulo rectângulo calcula o seu perímetro. O perímetro de uma figura geométrica éa soma dos comprimentos de todos os seus lados.

Os procedimentos descritos acima devem ser entregues electronicamente até dia 30 de Outubro.Uma vez que estes trabalhos vão ser executados para a verificação da sua correcção, é impres-cindível que os procedimentos tenham exactamente os nomes indicados.Para entregar este trabalho de casa, deve colocar os procedimentos pedidos num único ficheirodetexto, verificando depois que ele pode ser carregado pelo compilador de Scheme que utilizou.Depois disto, deve, no camoes, colocar-se na directoria onde esse ficheiro se encontra e dar oseguinte comando:/users/cadeiras/ic-ip/entrega-tpcEste comando irá pedir o número de aluno e o nome do ficheiro onde se encontra o TPC, enviandode seguida o trabalho por correio electrónico para um endereço de entregas da cadeira de IP.A resposta sobre o sucesso da entrega é de seguida enviada porcorreio electrónico para o ende-reço de onde se executou o comando.Trabalhos noutro formato ou que não sejam correctamente enviados por correio electrónico até àdata estipulada não serão considerados.Bom trabalho.Resposta:

Page 14: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

4 RECURSÃO 13

4 Recursão

Sumário O objectivo desta aula é que os alunos aprendam a construir procedimentos recursivose que se apercebam de como é que a recursão pode ser utilizada para implementar repetição.

Resumo Um procedimento recursivo é um procedimento definido à custade si próprio, isto é, que sechama a si mesmo.

Page 15: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

4 RECURSÃO 14

Exercícios

Exercício 4.1Defina um procedimento que calcula uma potência inteira dex. Note quexn = x∗xn−1 ex0 = 1.Resposta:

(define (potencia x n)(if (= n 0)

1( * x (potencia x (- n 1)))))

Exercício 4.2Considere definidos os seguintes procedimentos:add1 , sub1 e zero? , que somam um aoseu argumento, subtraem um ao seu argumento, ou testam se o seu argumento é igual a zero,respectivamente.Com base neles, defina os seguintes procedimentos:

1. O procedimentosoma, que recebe dois inteiros superiores ou iguais a zerox ey , e calculaa soma entre eles.

2. O procedimentoigual? , que dados dois inteiros superiores ou iguais a zerox ey , retornaverdadeiro se eles forem iguais e falso caso contrário.

3. O procedimentomenor? , que dados dois inteiros superiores ou iguais a zerox ey , indicasex é menor quey .

4. O procedimentoproduto , que calcula o produto entre dois inteiros superiores ou iguaisa zerox ey . Para definir este procedimento pode também usar o procedimentosoma.

Resposta:

1. (define (soma x y)(if (zero? x)

y(add1 (soma (sub1 x) y))))

2. (define (igual? x y)(cond ((zero? x) (zero? y))

((zero? y) #f)(else (igual? (sub1 x) (sub1 y)))))

3. (define (menor? x y)(cond ((zero? y) #f)

((zero? x) #t)(else (menor? (sub1 x) (sub1 y)))))

4. (define (produto x y)(if (zero? x)

0(soma (produto (sub1 x) y) y)))

Page 16: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

4 RECURSÃO 15

Exercício 4.3O número de combinações dem objectosn an pode ser calculado pela seguinte função:

Comb(m, n) =

1 sen = 0,

1 sen = m,

Comb(m − 1, n) + Comb(m − 1, n − 1) sem > n, m > 0 en > 0.

Escreva um procedimento que calcula o número de combinaçõesde m objectosn a n. Use aestrutura de blocos para garantir que o seu procedimento recebe sempre os argumentos correctos:inteiros superiores ou iguais a zero em > n.Sabendo que existem 49 números possíveis para o totoloto e que cada chave tem 6 númerosdiferentes, calcule o número de chaves existentes.Sabendo que cada aposta custa 40$00, quanto dinheiro teria que gastar para ter a certeza queganhava um primeiro prémio?Resposta:

(define (comb m n)(define (comb-aux m n)

(cond ((= n 0) 1)((= m n) 1)(else (+ (comb-aux (- m 1) n)

(comb-aux (- m 1) (- n 1))))))(if (and (>= m n)

(> m 0)(> n 0))

(comb-aux m n)#f))

Para calcular o número de chaves existentes para o totoloto,avaliar(comb 49 6) . (Vai demorar algumtempo) O resutado deverá ser13983816 .Para saber quanto dinheiro se tem que gastar, basta multiplicar este valor por 40$00, que é quanto custacada aposta;( * 13983816 40) , o que dá559352640 .Isto significa que, para ter a certeza de ganhar o primeiro premio, teria que gastar mais de 559352 contos!!!

Exercício 4.4(Livro — 1.4) Repare que o nosso modelo de avaliação permite aexistência de combinações cu-jos operadores são expressões compostas. Use esta observação para descrever o comportamentodo seguinte procedimento:

(define (a-plus-abs-b a b)((if (> b 0) + -) a b))

Resposta: Este procedimento somaa com o modulo deb, pois o operador utilizado é+ ou - , conformeb seja positivo ou negativo, respectivamente.

Exercício 4.5(Livro — 1.5) O Zé Só Bites inventou um teste para determinar se o interpretador com que ele sedeparou usa avaliação pela ordem aplicativa ou avaliação pela ordem normal. Ele define os doisprocedimentos:

Page 17: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

4 RECURSÃO 16

(define (p) (p))

(define (test x y)(if (= x 0)

0y))

E depois avalia a expressão

(test 0 (p))

Qual é o comportamento que o Zé vai observar com um interpretador que use a ordem de avali-ação aplicativa? Qual é o comportamento que ele vai observarcom um interpretador que use aordem de avaliação normal? Explique a sua resposta. (Assumaque a regra de avaliação para aforma especialif é a mesma, quer o interpretador use a ordem de avaliação aplicativa, quer usea ordem de avaliação normal: primeiro avalia o predicado e o resultado determina se deve avaliaro consequente ou a alternativa.)Resposta: Num Scheme que use a ordem aplicativa, como é o caso do que estamos a usar, os argumentossão avaliados antes de se aplicar o operador. Assim, para avaliar (test 0 (p)) , começa-se por ava-liar as sub-expressõestest , 0 e (p) e só depois é que se aplica o operador (resultante da avaliação detest ). Por isso, e uma vez quep corresponde a um ciclo infinito, a avaliacao de(test 0 (p)) nãovai terminar.

Num Scheme que use a ordem de avaliação normal (“fully expandand then reduce”), para avaliar(test

0 (p)) começa por expandir para(if (= 0 0) 0 (p)) e só depois é que vai começar a reduzir,aplicando a forma especialif aos seus argumentos. Neste caso, como a condição doif (= 0 0) temo valor verdadeiro, é a primeira alternativa que é avaliada eé retornado o valor0.

Exercício 4.6(Livro — 1.6) A Alice não percebe porque é que oif precisa de ser uma forma especial. “Porqueé que não o posso definir como um procedimento normal em termosdo cond ?” pergunta ela.Eva, uma amiga sua, diz que isso é possível e define uma nova versão doif :

(define (new-if predicate then-clause else-clause)(cond (predicate then-clause)

(else else-clause)))

A Eva demonstra o programa à Alice:

(new-if (= 2 3) 0 5)5

(new-if (= 1 1) 0 5)0

Encantada, a Alice usa onew-if para re-escrever o programa da raíz quadrada:

(define (improve guess x)(average guess (/ x guess)))

Page 18: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

4 RECURSÃO 17

(define (average x y)(/ (+ x y) 2))

(define (good-enough? guess x)(< (abs (- (square guess) x)) 0.001))

(define (sqrt-iter-new-if guess x)(new-if (good-enough? guess x)

guess(sqrt-iter-new-if (improve guess x)

x)))

(define (sqrt x)(sqrt-iter-new-if 1.0 x))

O que é que acontece quando a Alice tenta calcular raízes quadradas? Explique.Resposta: Como o new-if foi definido como sendo um procedimento normal,para ser avaliado vai terque avaliar os seus argumentos. Assim, quando queremos executar o procedimento sqrt-iter, vamos terque avaliar um new-if, que por sua vez vai ter que avaliar todos os seus argumentos, incluindo uma novachamada a sqrt-iter, que por sua vez corresponde à avaliacaode um new-if. E assim sucessivamente...

Exercício 4.7(Livro — 1.7) O testegood-enough? usado para calcular raízes quadradas não vai funcionarmuito bem para raízes de números muito pequenos. Para além disso, nos computadores reaisas operações aritméticas são quase sempre efectuadas com precisão limitada. Este facto torna onosso teste inadequado para números muito grandes. Explique estas afirmações, com exemplosque mostrem como é que o teste falha para números muito pequenos e muito grandes. Umaestratégia alternativa para implementar ogood-enough? é observar como é que oguessmuda de uma iteração para a próxima e parar quando a mudança é uma fracção pequena doguess . Escreva um procedimento para calcular raízes quadradas que use este tipo de teste determinação. Ela funciona melhor para números pequenos e grandes?

Exercício 4.8(Livro — 1.8) O método de Newton para calcular raízes cúbicasé baseado no facto que sey éuma aproximação para a raíz cúbica dex, então uma melhor aproximação é dada por

x

y2+2y

3

Use esta fórmula para implementar um procedimento que calcula raízes cúbicas análogo ao quecalcula raízes quadradas.Resposta:

(define (improve-cube guess x)(/ (+ (/ x (square guess))

( * 2 guess))3))

(define (cube x)( * x x x))

Page 19: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

4 RECURSÃO 18

(define (cubert-good-enough? guess x)(< (abs (- (cube guess) x)) 0.00001))

(define (cubert-iter guess x)(if (cubert-good-enough? guess x)

guess(cubert-iter (improve-cube guess x)

x)))

(define (cubert x)(cubert-iter 1.0 x))

Exercício 4.9Escreva um procedimento para calcular o valor desen(x) utilizando a expansão em série:

sen(x) =x

1!−

x3

3!+

x5

5!−

x7

7!+ . . .

O seu procedimento deve ter procedimentos para calcular o factorial e a potência.O seu procedimento deve também receber o número de termos quedevem ser considerados.Resposta:

(define (seno x n)(define (seno-iter cont acum)

(if (= cont n)acum(seno-iter (add1 cont)

(+ acum ( * (pot -1 cont)(/ (pot x (add1 ( * 2 cont)))

(fact (add1 ( * 2 cont)))))))))(if (>= n 1)

(seno-iter 0.0 0)(display "Tem que considerar pelo menos um termo.")))

(define (fact n)(if (= n 0)

1( * n (fact (sub1 n)))))

(define (pot x n)(if (= n 0)

1( * x (pot x (sub1 n)))))

Page 20: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

5 PROCESSOS ITERATIVOS VS RECURSIVOS RECURSÃO EM ÁRVORES 19

5 Processos iterativos vs recursivosRecursão em árvores

Sumário O objectivo desta aula é que os alunos aprendam a construir e distinguir entre processositerativos e recursivos.Para além disso, devem também dominar a recursão em ávores.

Resumo

Page 21: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

5 PROCESSOS ITERATIVOS VS RECURSIVOS RECURSÃO EM ÁRVORES 20

Exercícios

Exercício 5.1O número de combinações dem objectosn an pode ser calculado pela seguinte função:

Comb(m, n) =

1 sen = 0,

1 sen = m,

Comb(m − 1, n) + Comb(m − 1, n − 1) sem > n, m > 0 en > 0.

1. Escreva um procedimento que calcula o número de combinações dem objectosn an. Usea estrutura de blocos para garantir que o seu procedimento recebe sempre os argumentoscorrectos: inteiros superiores ou iguais a zero em ≥ n.

2. Sabendo que existem 49 números possíveis para o totoloto eque cada chave tem 6 númerosdiferentes, calcule o número de chaves existentes.

3. Sabendo que cada aposta custa 40$00, quanto dinheiro teria que gastar para ter a certezaque ganhava um primeiro prémio?

Resposta:

(define (comb m n)(define (comb-aux m n)

(cond ((= n 0) 1)((= m n) 1)(else (+ (comb-aux (- m 1) n)

(comb-aux (- m 1) (- n 1))))))(if (and (>= m n)

(> m 0)(> n 0))

(comb-aux m n)#f))

Para calcular o número de chaves existentes para o totoloto,avaliar(comb 49 6) . (Vai demorar algumtempo) O resutado deverá ser13983816 .Para saber quanto dinheiro se tem que gastar, basta multiplicar este valor por 40$00, que é quanto custacada aposta;( * 13983816 40) , o que dá559352640 .Isto significa que, para ter a certeza de ganhar o primeiro premio, teria que gastar mais de 559352 contos!!!

Exercício 5.2(Livro — 1.9) Cada um dos seguintes procedimentos define um método para adicionar doisinteiros positivos em termos dos procedimentosinc , que incrementa o seu argumento de umaunidade, edec , que decrementa o seu argumento de uma unidade.

(define (+ a b) (define (+ a b)(if (= a 0) (if (= a 0)

b b(inc (+ (dec a) b)))) (+ (dec a) (inc b))))

Usando o modelo da substituição, ilustre o processo gerado por cada procedimento ao avaliar(+ 4 5) . Estes processos são iterativos ou recursivos?Resposta:

Page 22: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

5 PROCESSOS ITERATIVOS VS RECURSIVOS RECURSÃO EM ÁRVORES 21

Exercício 5.3Defina um procedimento que calcula uma potência inteira dex usando um processo iterativo.Note quexn = x ∗ xn−1 ex0 = 1.Modifique o procedimento anterior para que passe também a conseguir calcular potências emque o expoente é negativo. Note quex−n = 1

xn .Resposta: Tal como já vimos, se usássemos um processo recursivo, ficaria:

(define (potencia x n)(if (zero? n)

1( * x (potencia x (sub1 n)))))

Alternativamente, podemos usar um processo iterativo, usando um procedimento auxiliar com mais umargumento que vai funcionar como acumulador:

(define (potencia x n)

(define (pot x n acc)(if (zero? n)

acc(pot x (sub1 n) ( * acc x))))

(pot x n 1))

Para tratar os expoentes negativos, temos que testar, no procedimento exterior, qual o valor do expoente, echamar o procedimento auxiliar da maneira adequada:

(define (potencia x n)

(define (pot x n acc)(if (zero? n)

acc(pot x (sub1 n) ( * acc x))))

(if (< n 0)(/ 1 (pot x (abs n) 1))(pot x n 1)))

Exercício 5.4Com base em somas e subtrações, defina o procedimentoproduto , que calcula o produto entredois inteiros superiores ou iguais a zerox ey .

1. Usando um processo recursivo

2. Usando um processo iterativo

Resposta: Usando um processo recursivo, fica:

(define (produto x y)(if (zero? y)

0(+ x (produto x (sub1 y)))))

Page 23: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

5 PROCESSOS ITERATIVOS VS RECURSIVOS RECURSÃO EM ÁRVORES 22

Usando um processo iterativo, fica:

(define (produto x y)(define (prod x y acc)

(if (zero? y)acc(prod x (sub1 y) (+ acc x))))

(prod x y 0))

Page 24: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

6 ORDENS DE CRESCIMENTO PROCEDIMENTOS DE ORDEM SUPERIOR 23

6 Ordens de crescimentoProcedimentos de ordem superior

Sumário

Resumo

Page 25: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

6 ORDENS DE CRESCIMENTO PROCEDIMENTOS DE ORDEM SUPERIOR 24

Exercícios

Exercício 6.1(Livro — 1.15) O seno de um ângulo (especificado em radianos) pode ser calculado usando aaproximação sinx ≈ x sex for suficientemente pequeno, e a identidade trigonométrica

sinx = 3 sinx

3− 4 sin3x

3

para reduzir o valor do argumento de sin. (Para este exercício, vamos considerar que um ânguloé “suficientemente pequeno” se a sua magnitude não for maior que 0.1 radianos.)Estas ideias estão incorporadas nos procedimentos seguintes:

(define (cube x)( * x x x))

(define (sine angle)(define (p x)

(- ( * 3 x)( * 4 (cube x))))

(if (<= (abs angle) 0.1)angle(p (sine (/ angle 3)))))

1. Quantas vezes é que o procedimentop é aplicado quando avaliamos(sine 12.5) ?

2. Qual é a ordem de crescimento em espaço e número de passos (em função dea) usadospelo processo gerado pelo procedimentosine quando avaliamos(sine a) ?

Resposta: Antes de começar, convém realçar que o procedimentop só serve para não ser necessáriocalcular 2 vezes o seno da terça parte do argumento. Ou seja, se usássemos olet , o procedimentosineficaria:

(define (sine angle)(if (<= (abs angle) 0.1)

angle(let ((x (sine (/ angle 3))))

(- ( * 3 x)( * 4 (cube x))))))

1. Ao avaliar(sine 12.5) , temos a seguinte sequência de chamadas:

(sine 12.5)(p (sine (/ 12.5 3)))(p (p (sine (/ 4.16 ··· 3))))(p (p (p (sine (/ 1.38 ··· 3)))))(p (p (p (p (sine (/ 0.462 ··· 3))))))(p (p (p (p (p (sine (/ 0.15 ··· 3))))))(p (p (p (p (p 0.05 ···)))))

Isto corresponde a 5 chamadas ao procedimentop.

Page 26: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

6 ORDENS DE CRESCIMENTO PROCEDIMENTOS DE ORDEM SUPERIOR 25

2. Para sabermos qual a ordem de crescimento do processo, temos que analizar como é que são assuas chamadas: vamos dividindo o argumento do procedimentopor três até o resultado ser menorque 0.1.Portanto, estamos interessados em saber quantas vezes é quetemos que dividir o argumento portrês até que o resultado seja menor que 0.1.Ou seja, estamos interessados em resolver a seguinte inequação em ordem an: a

3n ≤ 0, 1.Fazendo esse desenvolvimento, ficamos com

a ≤ 0, 1 ∗ 3n ⇔ 10a ≤ 3n ⇔ Log310a ≥ n

Isto significa que este procedimento tem ordem de crescimento em tempo e em espaço deLog310a.

Exercício 6.2(Livro — 1.29) A Regra de Simpson é um método para fazer integração numérica. Usando aRegra de Simpson, o integal de uma funçãof entrea e b pode ser aproximado por

h

3[y0 + 4y1 + 2y2 + 4y3 + 2y4 + . . . + 2yn−2 + 4yn−1 + yn]

ondeh = (b − a)/n, para algum inteiro parn, e yk = f(a + kh). (Aumentar on aumenta aprecisão da aproximação.) Defina um procedimento que recebecomo argumentosf , a, b e n eretorna o valor do integral, calculado usando a Regra de Simpson. Use o seu procedimento paraintegrar o procedimentocubo entre0 e 1 (comn = 100 e n = 1000), e compare os resultadoscom os do procedimentointegral apresentado na página 60 do livro.Nota: Deve usar o procedimentosum, definido na página 58 do livro, como

(define (sum term a next b)(if (> a b)

0(+ (term a)

(sum term (next a) next b))))

Resposta:

Exercício 6.3(Livro — 1.30) O procedimentosum apresentado acima gera recursão linear. No entanto, podeser escrito de forma a gerar um processo iterativo. Mostre como é que isso poderia ser feitopreenchendo as expressões que faltam na definição que se segue:

(define (sum term a next b)(define (iter a result)

(if <??><??>(iter <??> <??>)))

(iter <??> <??>))

Resposta:

Page 27: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

6 ORDENS DE CRESCIMENTO PROCEDIMENTOS DE ORDEM SUPERIOR 26

(define (sum term a next b)(define (iter a result)

(if (> a b)result(iter (next a) (+ (term a) result))))

(iter a 0))

Exercício 6.4(Livro — 1.31)

1. O procedimentosum é apenas o mais simples de um vasto número de abstracções seme-lhantes, que podem ser capturadas como procedimentos de ordem superior. Escreva umprocedimento análogo chamadoproduct , que retorna o produto dos valores de uma fun-ção para pontos pertencentes a um intervalo. Mostre como definir o factorial emtermos doproduct . Use também oproduct para calcular aproximações deπ usandoa fórmula

π

4=

2 · 4 · 4 · 6 · 6 · 8 . . .

3 · 3 · 5 · 5 · 7 · 7 . . .

2. Se o seu procedimentoproduct gerar um processo recursivo, escreva um que gere umprocesso iterativo. Se gerar um processo iterativo, escreva um que gere um processo recur-sivo.

Resposta:

1. (define (product term a next b)(if (> a b)

1( * (term a)

(product term (next a) next b))))

(define (fact n)(product (lambda (x) x) 1 add1 n))

Para calcular as aproximações deπ, podemos separar a fórmula anterior em duas, e considerar que

π

4=

2 · 4 · 6 . . .

3 · 5 · 7 . . .·4 · 6 · 8 . . .

3 · 5 · 7 . . .

Podemos usar oproduct para calcular o valor de cada uma destas fracções. Depois, basta multi-plicar o resultado por 4 para ficarmos com o valor deπ:

(define (pi n)(define (numerator n) ( * 2 n))(define (denominator n) (add1( * 2 n)))( * 4 ( * (/ (product numerator 1.0 add1 (/ n 2))

(product denominator 1.0 add1 (/ n 2)))(/ (product numerator 2.0 add1 (add1 (/ n 2)))

(product denominator 1.0 add1 (/ n 2))))))

No entanto, esta versão funciona mal, porque tanto o numerador como o denominador atingemfalores muito altos e fazem overflow.Mas também podemos considerar que a série, desde o termo1 até ao termon vai progredindo da

Page 28: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

6 ORDENS DE CRESCIMENTO PROCEDIMENTOS DE ORDEM SUPERIOR 27

seguinte forma: nos termos de índice par, o numerador é o índice mais dois e o denominador oíndice mais um; nos termos de índice ímpar, o numerador é o índice mais um e o denominador oíndice mais dois. Assim, ficamos com o procedimento seguinte:

(define (pi n)(define (term k)

(if (even? k)(/ (+ k 2) (+ k 1))(/ (+ k 1) (+ k 2))))

( * 4 (product term 1 add1 n)))

2. (define (product term a next b)(define (iter a result)

(if (> a b)result(iter (next a)

( * (term a) result))))(iter a 1))

Exercício 6.5(Livro — 1.32)

1. Mostre quesum e product são ambos casos especiais de uma noção ainda mais geralchamadaaccumulate , que combina uma coleção de termos, usando uma função deacumulação geral:

(accumulate combiner null-value term a next b)

Accumulate recebe como argumentos o mesmoterm e as mesmas especificações dointervaloa eb, bem como um procedimentocombiner (de 2 argumentos) que especificacomo é que o termo corrente deve ser combinado com a acumulação dos termos prece-dentes e umnull-value , que especifica qual o valor a usar quando os termos acabam.Escreva o procedimentoaccumulate e mostre como é quesum eproduct podem serdefinidos como simples chamadas aaccumulate .

2. Se o seu procedimentoaccumulate gerar um processo recursivo, escreva um que gereum processo iterativo. Se gerar um processo iterativo, escreva um que gere um processorecursivo.

Resposta:

1. (define (accumulate combiner null-value term a next b)(if (> a b)

null-value(combiner (term a)

(accumulate combinernull-valueterm(next a)next

Page 29: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

6 ORDENS DE CRESCIMENTO PROCEDIMENTOS DE ORDEM SUPERIOR 28

b))))

(define (sum term a next b)(accumulate + 0 term a next b))

(define (product term a next b)(accumulate * 1 term a next b))

2. (define (accumulate combiner null-value term a next b)(define (iter a result)

(if (> a b)null-value(iter (next a)

(combiner (term a) result))))(iter a null-value))

Exercício 6.6(Livro — 1.34) Suponha que definimos o procedimento

(define (f g)(g 2))

Assim, temos:

(f quadrado)4

(f (lambda (z) ( * z (+ z 1))))6

O que acontece se (perversamente) pedirmos ao interpretador para avaliar(f f) ? Explique.Resposta: Ao avaliar(f f) , temos a seguinte sequência de avaliações:

(f f)(f 2)(2 2)

Como2 não é o nome de nenhum procedimento, ao avaliar a última expressão vamos obter um erro, poisnão é possível aplicar o “procedimento”2 a nenhuns argumentos.

Exercício 6.71. Escreva um procedimento que faz a composição de procedimentos. Por exemplo, a cha-

mada(compoe f g x) aplica o procedimentof ao resultado de aplicar o procedimentog ax .

2. Com base no procedimentocompoe, escreva um procedimentotriplo-fact , que cal-cula o triplo do factorial do seu argumento. Por exemplo,(triplo-fact 3) deverádar 18.

Resposta:

1. (define (compoe f g x)(f (g x)))

Page 30: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

6 ORDENS DE CRESCIMENTO PROCEDIMENTOS DE ORDEM SUPERIOR 29

2. (define (triplo-fact x)(compoe (lambda (x) ( * x 3)) fact x))

Exercício 6.8Com base no procedimentosum, escreva um procedimento para calcular o valor desen(x) uti-lizando a expansão em série:

sen(x) =x

1!−

x3

3!+

x5

5!−

x7

7!+ . . .

Assuma que já existem os procedimentosfact e pot que calculam o factorial e a potência,respectivamente.O seu procedimento deve receber, para além dex, o númeron de termos que devem ser conside-rados.Resposta:

(define (fact n)(if (= n 0)

1( * n (fact (sub1 n)))))

(define (sum term a next b)(if (> a b)

0(+ (term a)

(sum term (next a) next b))))

(define (seno-com-sum x n)(if (< n 1)

(display "Tem que considerar pelo menos um termo.")(sum (lambda (n)

( * (expt -1 (sub1 n))(/ (expt x (sub1 ( * 2 n)))

(fact (sub1 ( * 2 n))))))1add1n)))

Outra possibilidade para definir o procedimentoseno-com-sum seria definir um procedimento auxiliarchamado, por exemplo,term . Tanto no caso de usarmos alambda como no caso do procedimentoauxiliar, temos que nos lembrar que osum recebe um procedimento deum argumento. Por isso, mesmoque quiséssemos, por questão de clareza incluir mais argumentos, neste caso isso não seria possível. Como procedimento auxiliar,seno-com-sum ficaria:

(define (seno-com-sum x n)(define (term n)

( * (expt -1 (sub1 n))(/ (expt x (sub1 ( * 2 n)))

(fact (sub1 ( * 2 n))))))(if (< n 1)

(display "Tem que considerar pelo menos um termo.")(sum term 1 add1 n)))

Page 31: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

6 ORDENS DE CRESCIMENTO PROCEDIMENTOS DE ORDEM SUPERIOR 30

Exercício 6.9Suponha que tem definido o procedimentocomb, que recebe dois inteiros maiores ou iguais azero,men, e calcula o número de combinações demelementosn an.Sabendo que existem 49 números possíveis para o totoloto e que cada chave tem 6 númerosdiferentes, escreva um procedimento que escreve quanto dinheiro tem que ser gasto para tera certeza de ganhar o primeiro prémio do totoloto, se as apostas custassem 40$00, 50$00 ou60$00.Resposta:

(define (comb m n)(define (comb-aux m n)

(cond ((= n 0) 1)((= m n) 1)(else (+ (comb-aux (- m 1) n)

(comb-aux (- m 1) (- n 1))))))(if (and (>= m n)

(> m 0)(> n 0))

(comb-aux m n)#f))

(define (precosTotoloto)(let ((x (comb 49 6)))

(display "Se as apostas custarem 40$00, tem que gastar ")(display ( * 40 x))(newline)(display "Se as apostas custarem 50$00, tem que gastar ")(display ( * 50 x))(newline)(display "Se as apostas custarem 60$00, tem que gastar ")(display ( * 60 x))))

(precosTotoloto)

Page 32: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

7 MÉTODOS GERAIS: PROCEDIMENTOS QUE RETORNAM PROCEDIMENTOS 31

7 Métodos gerais: procedimentos que retornam procedimen-tos

Sumário

Resumo

Page 33: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

7 MÉTODOS GERAIS: PROCEDIMENTOS QUE RETORNAM PROCEDIMENTOS 32

Exercícios

Exercício 7.1Considere definido o procedimentosum:

(define (sum term a next b)(if (> a b)

0(+ (term a)

(sum term (next a) next b))))

Diga o que fazem as seguintes chamadas a esse procedimento:

1. (sum (lambda (x) x) 4 add1 500)

2. (sum (lambda (x) (sqrt x)) 5 (lambda (x) (+ x 5)) 500)

3. (sum (lambda (x) (sum (lambda (x) x) 1 add1 x)) 1 add1 5)

Resposta:

1. Soma os números entre 4 e 500.

2. Soma as raízes quadradas dos múltiplos de 5 entre 5 e 500.

3. Para cada um dos números entre 1 e 5, soma os números entre 1 eesse número:(1+(1+2)+(1+2 + 3) + (1 + 2 + 3 + 4) + (1 + 2 + 3 + 4 + 5))

Exercício 7.2Considere a seguinte expressão matemática:3x! + 4(x!)3

1. Escreva um procedimentocalc-expr que calcule o seu valor.

2. Usando a estrutura de blocos, garanta que o seu procedimento recebe sempre um argu-mento correcto (x ≥ 0).

3. Comente as afirmações seguintes:

(a) Neste caso, não havia necessidade de utilizar a estrutura de blocos.

(b) Neste caso, convém utilizar a forma especiallet .

(c) Neste caso, não devo definir o procedimentocubo .

(d) O procedimentocubo , se for definido, deve ser definido dentro do procedimentocalc-expr .

Resposta:

1. (define (fact x)(if (zero? x)

1( * x (fact (sub1 x)))))

(define (calc-expr x)(let ((x-fact (fact x)))

(+ ( * 3 x-fact)( * 4 (expt x-fact 3)))))

Page 34: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

7 MÉTODOS GERAIS: PROCEDIMENTOS QUE RETORNAM PROCEDIMENTOS 33

2. (define (calc-expr x)(define (calc-expr-aux x)

(let ((x-fact (fact x)))(+ ( * 3 x-fact)

( * 4 (expt x-fact 3)))))(if (>= x 0)

(calc-expr-aux x)(display "ERRO: o arg deve ser um inteiro positivo.")))

3. (a) É verdade que não havia necessidade de utilizar a estrutura de blocos, pois o teste se o argu-mento é válido só seria feito uma vez, mesmo que fosse feito noprocedimento exterior. Fariasentido usar a estrutura de blocos se o procedimento fosse recursivo, para evitar a repetiçãodo teste a cada iteração.

(b) É verdade que convém utilizar a forma especiallet , pois assim podemos guardar o valor dex!, que de outra forma teria que ser calculado duas vezes.

(c) Esta afirmação não é verdadeira, pois aquilo que o procedimentocubo faz é uma operaçãobem definida e que pode ser útil noutros procedimentos. Assim, faz sentido definir esteprocedimento.

(d) Tal como já dissémos, o procedimentocubo pode ser útil noutros procedimentos. Por isso,deve ser definido fora do procedimentocalc-expr .

Exercício 7.3(Livro — 1.41) Defina um procedimento que recebe como argumento um procedimento de umargumento e retorna um procedimento que aplica duas vezes o procedimento original.Por exemplo, seadd1 for um procedimento que adiciona 1 ao seu argumento, então(doubleadd1) deverá ser um procedimento que adiciona dois:

((double add1) 5)7(((double double) add1) 5)9

Qual é o valor retornado por(((double (double double)) add1) 5) ? Porquê?Resposta:

(define (double proc)(lambda (x) (proc (proc x))))

>((double add1) 5)7>(((double double) add1) 5)9>(((double (double double)) add1) 5)21

Para explicarmos estes resultados, podemos analizar os vários passos pelos quais passa a avaliação de cadauma destas expressões:

((double add1) 5)((lambda (x) (add1 (add1 x))) 5)

Page 35: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

7 MÉTODOS GERAIS: PROCEDIMENTOS QUE RETORNAM PROCEDIMENTOS 34

(add1 (add1 5))(add1 6)7

Para a segunda expressão, fica:

(((double double) add1) 5)(((lambda (x) (double (double x))) add1) 5)((double (double add1)) 5)((double (lambda (x) (add1 (add1 x)))) 5)((lambda (x2) ((lambda (x) (add1 (add1 x)))

((lambda (x) (add1 (add1 x))) x2))) 5)((lambda (x) (add1 (add1 x))) (lambda (x) (add1 (add1 x)) 5))((lambda (x) (add1 (add1 x))) (add1 (add1 5)))((lambda (x) (add1 (add1 x))) (add1 6))((lambda (x) (add1 (add1 x))) 7)(add1 (add1 7))(add1 8)9

Para a última expressão, fica:

(((double (double double)) add1) 5)21

Exercício 7.41. (Livro — 1.42) Sejamf e g duas funções de um argumento. A composiçãof depois de

g é definida como sendo a funçãox 7→ f(g(x)). Defina um procedimentocompose queimplementa a composição. Por exemplo, seinc for um procedimento que adiciona 1 aoseu argumento,

((compose square inc) 6)49

2. Compare o procedimentocompose com o procedimentocompoe da aula passada. Por-que é que eles são diferentes?

Resposta:

1. (define (compose f g)(lambda (x) (f (g x))))

2. O procedimentocompoe da aula passada recebia os procedimentos a compor e também osar-gumentos desses procedimentos. Retornava o resultado da aplicação dos procedimentos ao valorrecebido.O procedimentocompose recebe apenas os procedimentos e retorna outro procedimento.O resultado do procedimentocompose pode ser usado como primeiro elemento de uma expressãoem Scheme e o resultado do procedimentocompoe não.

Page 36: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

7 MÉTODOS GERAIS: PROCEDIMENTOS QUE RETORNAM PROCEDIMENTOS 35

Exercício 7.5(Livro — 1.43) Sef for uma função numérica en um inteiro positivo, então podemos for-mar an-ésima repetição da aplicação def , que é definida como a função cujo valor emx éf(f(. . . (f(x)) . . .)).Por exemplo, sef for a funçãox 7→ x+1, então an-ésima repetição da aplicação def é a funçãox 7→ x + n.Sef for a operação de elevar um número ao quadrado, então an-ésima repetição da aplicaçãodef é a função que eleva o seu argumento a2n.Escreva um procedimento chamadorepeated , que recebe como argumentos um procedimentoque calculaf e um inteiro positivon e retorna um procedimento que calcula an-ésima repetiçãoda aplicação def . O seu procedimento deverá poder ser usado da seguinte forma:

((repeated square 2) 5)625

Sugestão: Pode ser conveniente usar ocompose do execício anterior.Resposta:

(define (repeated f n)(if (= n 1)

f(compose f (repeated f (sub1 n)))))

Exercício 7.6(Livro — 1.44) A ideia de alisar uma função é um conceito importante em processamento desinal. Sef é uma função edx é um número pequeno, então a versão alisada def é a função cujovalor no pontox é a média def(x − dx), f(x) ef(x + dx).Escreva um procedimentosmooth que recebe como argumento um procedimento que calculafe retorna um procedimento que calculaf alisada.Algumas vezes, pode ser útil alisar repetidamente uma função (isto é, alisar a função alisada eassim sucessivamente) para obter a função alisada n-vezes.Mostre como é que poderia gerar afunção alisada n-vezes de qualquer função usandosmooth e repeated do exercício anterior.Resposta:

(define (smooth f)(let ((dx 0.00001))

(lambda (x) (/ (+ (f (- x dx))(f x)(f (+ x dx)))

3))))

(define (n-fold-smooth f n)((repeated smooth n) f))

Page 37: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

8 ABSTRACÇÃO DE DADOS PARES EM SCHEME 36

8 Abstracção de dadosPares em Scheme

Sumário

Resumo

Page 38: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

8 ABSTRACÇÃO DE DADOS PARES EM SCHEME 37

Exercícios

Exercício 8.1Diga qual o resultado de avaliar cada uma das seguintes expressões. Se alguma delas der origema um erro, explique porquê.

(cons 2 3)

(car (cons 2 3))

(cddr (cons 2 3))

(cdr (cons "ola" "bom dia"))

(list (cons 1 3) 4)

(cdr (list 2 3))

(cdr (cons 2 3))

()

(list ())

(cons (integer? (sqrt 4)) (integer? 2.0))

(pair? (cons 2 3))

(list? (cons 2 3))

(list? (list 2 3))

(pair? (list 2 3 4))

(cadr (list 2 3 4))

Resposta:

>(cons 2 3)(2 . 3)

>(car (cons 2 3))2

>(cddr (cons 2 3))cddr: expects argument of type <cddrable value>; given (2 . 3)

>(cdr (cons "ola" "bom dia"))"bom dia"

Page 39: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

8 ABSTRACÇÃO DE DADOS PARES EM SCHEME 38

>(list (cons 1 3) 4)((1 . 3) 4)

>(cdr (list 2 3))(3)

>(cdr (cons 2 3))3

>()()

>(list ())(())

>(cons (integer? (sqrt 4)) (integer? 2.0))(#t . #t)

>(pair? (cons 2 3))#t

>(list? (cons 2 3))#f

>(list? (list 2 3))#t

>(pair? (list 2 3 4))#t

>(cadr (list 2 3 4))3

Exercício 8.2Represente as seguintes listas e pares usando a notação de caixas e ponteiros:

1. (1)

2. (1 . 2)

3. (1 2)

4. (1 (2 (3 (4 5))))

5. (1 (2 . 3) 4)

6. (((2 (6 (7 . 8) 3)) 1))

7. (1 (((2))))

Resposta:

Page 40: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

8 ABSTRACÇÃO DE DADOS PARES EM SCHEME 39

Exercício 8.3Considere as seguintes definições para o procedimentomake-rat , que, dados dois inteiros,retorna o racional em que o primeiro é o numerador e o segundo éo denominador:

(define (make-rat n d)(cons n d))

(define (make-rat n d)(let ((g (gcd n d)))

(cons (/ n g) (/ d g))))

Em relação à primeira definição, a segunda tem a vantagem de reduzir o numerador e o denomi-nador aos números mais pequenos possível.

(Livro — 2.1) Defina uma versão melhor demake-rat que considere argumentos positivos enegativos.make-rat deve normalizar o sinal, de forma a que, se o número racional for positivo,tanto o numerador como o denominador são positivos; e se o número racional for negativo, só onumerador é que é negativo.Resposta:

(define (gcd a b)(if (= b 0)

a(gcd b (remainder a b))))

(define (make-rat n d)(let ((g (gcd (abs n) (abs d))))

(if (>= ( * n d) 0)(cons (/ (abs n) (abs g)) (/ (abs d) (abs g)))(cons (- (/ (abs n) g)) (/ (abs d) g)))))

Exercício 8.4(Livro — 2.2) Considere o problema de representar segmentosde recta num plano. Cada seg-mento é representado por um par de pontos: um ponto inicial e um ponto final.Defina um construtormake-segment e os selectoresstart-segment e end-segmentque definem a representação dos segmentos em termos de pontos.

Adicionalmente, um ponto pode ser representado como um par de números: a coordenadax e acoordenaday.Especifique o construtormake-point e os selectoresx-point ey-point que definem estarepresentação.

Usando os seus selectores e construtores, defina um procedimentomidpoint-segment querecebe um segmento de recta como argumento e retorna o seu ponto médio (o ponto cujas coor-denadas são a média das coordenadas dos pontos que definem o segmento).Resposta:

(define (make-segment ip fp)(cons ip fp))

Page 41: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

8 ABSTRACÇÃO DE DADOS PARES EM SCHEME 40

(define (start-segment seg)(car seg))

(define (end-segment seg)(cdr seg))

;====

(define (make-point x y)(cons x y))

(define (x-point p)(car p))

(define (y-point p)(cdr p))

;====

(define (midpoint-segment seg)(let ((x1 (x-point (start-segment seg)))

(y1 (y-point (start-segment seg)))(x2 (x-point (end-segment seg)))(y2 (y-point (end-segment seg))))

(make-point (/ (+ x1 x2) 2)(/ (+ y1 y2) 2))))

Exercício 8.5(Livro — 2.3) Implemente uma representação de rectângulos num plano. (Pode ser útil usar osresultados do exercício anterior.)Com base nos seus construtores e selectores, crie procedimentos que calculem o perímetro e aárea de um dado rectângulo.

Implemente uma representação diferente para os rectângulos.Consegue conceber o seu sistema com as barreiras de abstração adequadas, de forma a que osprocedimentos que calculam a área e o perímetro funcionem com qualquer das representações?Resposta: Antes de mais nada, devemos definir a interface dos procedimentos que vão manipular rectân-gulos. Os rectângulos vão ser sempre definidos à custa de quatro valores: as coordenadasy do seu ladosuperior (top ) e do seu lado inferior (bottom ) e as coordenadasx do seu lado esquerdo (left ) e doseu lado direito (right ).Os selectores vão dar precisamente cada um destes valores, independentemente da representação internaque for usada para os rectângulos.

; Numa implementacao, vamos definir os rectangulos como um p ar de pontos,; o TopLeft e o BottomRight(define (make-rect top left right bottom)

(cons (make-point left top) ; a primeira coordenada dos pont os e’ x(make-point right bottom)))

Um melhoramento seria escrever o procedimento make-rect deforma a que este verificasse se os valoesrecebidos fazem sentido (por exemplo, left< right).

Page 42: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

8 ABSTRACÇÃO DE DADOS PARES EM SCHEME 41

(define (top-left-rect rect)(car rect))

(define (bottom-right-rect rect)(cdr rect))

(define (top rect)(y-point (top-left-rect rect)))

(define (left rect)(x-point (top-left-rect rect)))

(define (bottom rect)(y-point (bottom-right-rect rect)))

(define (right rect)(x-point (bottom-right-rect rect)))

(define (width rect)(- (right rect)

(left rect)))

(define (height rect)(- (top rect)

(bottom rect)))

(define (perimeter rect)( * 2

(+ (width rect)(height rect))))

(define (area rect)( * (width rect)

(height rect)))

Exercício 8.6Com base nas respostas aos exercícios anteriores, escreva um procedimentodentro-rectangulo ,que recebe um rectângulo e um ponto e retorna#t se o ponto estiver dentro do rectângulo (in-cluindo a fronteira) e#f se estiver fora do rectângulo.Resposta:

(define (dentro-rectangulo pt rect)(and (>= (top rect) (y-point pt) (bottom rect))

(>= (right rect) (x-point pt) (left rect))))

Exemplos:

>(dentro-rectangulo (make-point 2 3)(make-rect 5 1 5 1))

#t

Page 43: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

8 ABSTRACÇÃO DE DADOS PARES EM SCHEME 42

>(dentro-rectangulo (make-point 10 10)(make-rect 5 1 5 1))

#f

>(dentro-rectangulo (make-point 1 5)(make-rect 5 1 5 1))

#t

Exercício 8.7Defina os seguintes procedimentos que operam sobre listas. Os seus procedimentos devem darerro (usando oerror ) quando isso se justificar. Quando for possível, escreva dois procedimen-tos, um que gera um processo recursivo e outro que gera um processo iterativo.

1. O procedimentoprimeiro-par que recebe uma lista e retorna um par com os doisprimeiros elementos da lista.

2. O procedimentomaior-elemento que recebe uma lista de inteiros e retorna o maiorelemento dessa lista.

3. O procedimentosoma-elementos que recebe uma lista e retorna a soma de todos oselementos dessa lista.

4. O procedimentoaplica-op-com-passo que recebe uma lista e dois procedimentose retorna outra lista, cujos elementos são obtidos aplicando o primeiro procedimento aoprimeiro elemento da lista inicial, e das sucessivas listasque são obtidas por aplicação dosegundo procedimento (até que a lista fique vazia). Por exemplo,

(aplica-op-com-passo (list 1 2 3 4 5) (lambda (x) ( * 2 x)) cddr)

deverá retornar(2 6 10) .

5. O procedimentoimprime-lista-de-pares que recebe uma lista de pares e imprimeos pares, um por linha. O seu procedimento deve assinalar quando é que chega ao fim dalista. Por exemplo,

(imprime-lista-de-pares (list (cons "Luisa" 12345678)(cons "Jorge" 23456789)(cons "Maria" 34567890)(cons "Rui" 45678901)))

Deverá imprimir

Luisa -> 12345678Jorge -> 23456789Maria -> 34567890Rui -> 45678901Fim da lista

Resposta:

Page 44: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

8 ABSTRACÇÃO DE DADOS PARES EM SCHEME 43

1. (define (primeiro-par l)(if (and (pair? l) (pair? (cdr l)))

(cons (car l) (cadr l))(error "primeiro-par: espera uma lista com pelo menos

2 elementos, recebeu" l)))

Exemplos:

>(primeiro-par ())primeiro-par: espera uma lista com pelo menos 2 elementos, r ecebeu ()>(primeiro-par (list 1))primeiro-par: espera uma lista com pelo menos 2 elementos, r ecebeu (1)>(primeiro-par (list 1 2 3 4)))(1 . 2)>(primeiro-par (list 1 (cons 2 3) 4))(1 2 . 3)

Neste caso, não vamos gerar nenhum processo recursivo, poisisso não tem interesse.

2. (define (maior-elemento l)(define (m-e-aux l)

(if (null? (cdr l))(car l)(max (car l)

(m-e-aux (cdr l)))))(if (or (null? l) (not (pair? l)))

(error "maior-elemento: espera uma lista com pelo menos1 elemento, recebeu" l)

(m-e-aux l)))

Para o procedimento maior-elemento gerar um processo iterativo, usamos o seguinte:

(define (maior-elemento l)(define (m-e-aux l maximo)

(if (null? l)maximo(m-e-aux (cdr l) (max (car l) maximo))))

(if (or (null? l) (not (pair? l)))(error "maior-elemento: espera uma lista com pelo menos

1 elemento, recebeu" l)(m-e-aux (cdr l) (car l))))

Exemplos:

>(maior-elemento ())maior-elemento: espera uma lista com pelo menos 1 elemento, recebeu ()>(maior-elemento (list 1 5 2 10 4))10

3. (define (soma-elementos l)(if (null? l)

0(+ (car l)

Page 45: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

8 ABSTRACÇÃO DE DADOS PARES EM SCHEME 44

(soma-elementos (cdr l)))))

Para gerar um processo iterativo, precisamos de um argumento auxiliar e por causa disso de umprocedimento auxiliar

(define (soma-elementos l)(define (s-e-aux l acc)

(if (null? l)acc(s-e-aux (cdr l) (+ (car l) acc))))

(s-e-aux l 0))

Exemplos:

>(soma-elementos (list 1 5 2 10 4))22

4. (define (aplica-op-com-passo l p1 p2)(if (null? l)

()(cons (p1 (car l))

(aplica-op-com-passo (p2 l) p1 p2))))

Exemplos:

(aplica-op-com-passo (list 1 2 3 4 5) (lambda (x) ( * 2 x)) cddr)cddr: expects argument of type <cddrable value>; given (5)

O problema foi que no último passo da recursão chamámosp2 com(5) , o que originou este erro.No entanto, no procedimentoaplica-op-com-passo não podemos resolver este problema,pois não sabemos qual vai ser o procedimento passado no terceiro argumento. Assim, quandochamarmosaplica-op-com-passo é que vamos ter o cuidado de passar uma lista que não váoriginar um erro. Neste exemplo, a lista deveria ter mais um elemento, mas que não vai ser usadopara nada. Por exemplo:

(aplica-op-com-passo (list 1 2 3 4 5 ()) (lambda (x) ( * 2 x)) cddr)(2 6 10)

Outra alternativa seria que o segundo procedimento testasse se pode ser aplicado, de modo a nãodar erro. Por exemplo:

(aplica-op-com-passo (list 1 2 3 4 5)(lambda (x) ( * 2 x))(lambda (x) (if (>= (length x) 2)

(cddr x)())))

Para gerar um processo iterativo, precisamos de um argumento auxiliar e por causa disso de umprocedimento auxiliar. Uma possibilidade é:

(define (aplica-op-com-passo l p1 p2)(define (a-o-c-p-aux l res)

(if (null? l)res(a-o-c-p-aux (p2 l) (cons (p1 (car l)) res))))

(a-o-c-p-aux l ()))

Page 46: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

8 ABSTRACÇÃO DE DADOS PARES EM SCHEME 45

Exemplos:

(aplica-op-com-passo (list 1 2 3 4 5 ()) (lambda (x) ( * 2 x)) cddr)(10 6 2)

O problema é que assim ficamos com a lista de resultados invertida! Não é trivial criar um processoiterativo neste caso, pois não sabemos acrescentar elementos no fim de listas. Para isso deveríamosdefinir um outro procedimento, mas ficaria muito pouco eficiente porque tinha que percorrer sempretoda a lista, e assim iríamos perder as vantagens dos processos iterativos.

5. (define (imprime-lista-de-pares lista)(cond ((null? lista) (display "Fim da lista"))

((not (pair? (car lista)))(error "imprime-lista-de-pares: espera uma lista de pares ,

recebeu" lista))(else (display (caar lista))

(display " -> ")(display (cdar lista))(newline)(imprime-lista-de-pares (cdr lista)))))

Exemplos:

>(imprime-lista-de-pares (list (cons "Luisa" 12345678)(cons "Jorge" 23456789)(cons "Maria" 34567890)(cons "Rui" 45678901)))

Luisa -> 12345678Jorge -> 23456789Maria -> 34567890Rui -> 45678901Fim da lista

>(imprime-lista-de-pares (list (cons "Luisa" 12345678)(cons "Jorge" 23456789)(cons "Maria" 34567890)"Rui"))

Luisa -> 12345678Jorge -> 23456789Maria -> 34567890imprime-lista-de-pares: espera uma lista de pares, recebe u ("Rui")

Este exemplo gera um processo iterativo e neste caso não faz sentido criar um recursivo.

Page 47: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

9 LISTAS EM SCHEME 46

9 Listas em Scheme

Sumário

Resumo

Page 48: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

9 LISTAS EM SCHEME 47

Exercícios

Exercício 9.1(Livro — 2.17) Defina um procedimentolast-pair , que retorna a lista que contém apenas oúltimo elemento de uma dada lista não vazia:

(define (last-pair l)(if (null? (cdr l))

l(last-pair (cdr l))))

Exemplos:

>(last-pair (list 23 72 149 34))(34)>(last-pair ())cdr: expects argument of type <pair>; given ()>(last-pair (list ()))(())

Resposta:

Exercício 9.2(Livro — 2.18) Defina um procedimentoreverse , que recebe como argumento uma lista eretorna uma lista com os mesmos elementos, mas pela ordem inversa:

(reverse (list 1 4 9 16 25))(25 16 9 4 1)

Resposta:

(define (reverse l)(if (null? l)

()(cons (car l)

(reverse (cdr l)))))

Exemplos:

>(reverse (list 1 4 9 16 25))(1 4 9 16 25)

Mas este procedimento não inverte a lista! Precisamos de ir tirando os elementos do início da lista e ircolocando numa lista auxiliar. Para isso, definimos um procedimento auxiliar:

(define (reverse l)(define (r-aux l res)

(if (null? l)res(r-aux (cdr l) (cons (car l) res))))

(r-aux l ()))

Exemplos:

Page 49: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

9 LISTAS EM SCHEME 48

>(reverse (list 1 4 9 16 25))(25 16 9 4 1)

Exercício 9.3Defina um procedimentomap, que recebe como argumentos um procedimento de um argumentoe uma lista, e retorna a lista dos resultados produzidos aplicando o procedimento a cada elementoda lista.

(map abs (list -10 2.5 -11.6 17))(10 2.5 11.6 17)

Resposta:

(define (map proc l)(if (null? l)

()(cons (proc (car l))

(map proc (cdr l)))))

Exemplos:

>(map abs (list -10 2.5 -11.6 17))(10 2.5 11.6 17)>(map (lambda (x) ( * x 5)) (list 1 2 3 4 5))(5 10 15 20 25)

Exercício 9.4(Livro — 2.21) O procedimentosquare-list recebe como argumento uma lista de númerose retorna uma lista com os quadrados desses números.

(square-list (list 1 2 3 4))(1 4 9 16)

Seguem-se duas definições diferentes para o procedimentosquare-list . Complete ambas asdefinições, preenchendo as expressões que faltam:

(define (square-list items)(if (null? items)

()(cons <??> <??>)))

(define (square-list items)(map <??> <??>))

Resposta:

(define (square-list items)(if (null? items)

()(cons ((lambda (x) ( * x x)) (car items))

(square-list (cdr items)))))

(define (square-list items)(map (lambda (x) ( * x x)) items))

Page 50: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

9 LISTAS EM SCHEME 49

Exemplos:

>(square-list (list 1 2 3 4))(1 4 9 16)

Exercício 9.5(Livro — 2.22) O Luís tenta re-escrever o primeiro procedimento square-list do exercícioanterior de modo a que ele passe a gerar um processo iterativo:

(define (square-list items)(define (iter things answer)

(if (null? things)answer(iter (cdr things)

(cons ((lambda (x) ( * x x)) (car items))answer))))

(iter items ()))

Infelizmente, definir o procedimentosquare-list desta maneira produz a lista de respostapela ordem inversa à desejada. Porquê?O Luís tenta então corrigir este erro trocando os argumentosdo cons :

(define (square-list items)(define (iter things answer)

(if (null? things)answer(iter (cdr things)

(cons answer((lambda (x) ( * x x)) (car items))))))

(iter items ()))

Isto também não funciona. Explique porquê.Resposta:

Exemplos:

Exercício 9.6(Livro — 2.23) O procedimentofor-each é semelhante aomap. Recebe como argumentosum procedimento e uma lista de elementos. No entanto, em vez de formar uma lista com osresultados,for-each apenas aplica o procedimento a cada um dos elementos de cada vez, daesquerda para a direita. Os valores retornados pela aplicação do procedimento aos elementosnão são usados —for-each é usado com procedimentos que executam uma acção, tal comoimprimir. Por exemplo:

Page 51: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

9 LISTAS EM SCHEME 50

(for-each (lambda (x) (newline) (display x))(list 57 321 28))

5732128

O valor retornado pela chamada afor-each (não ilustrado acima) pode ser qualquer coisa,como verdadeiro. Apresente uma implementação para o procedimentofor-each .Resposta:

(define (for-each p l)(cond ((null? l) #t)

(else (p (car l))(for-each p (cdr l)))))

Exemplos:

>(for-each (lambda (x) (newline) (display x))(list 57 321 28))

5732128#t

Exercício 9.7Implemente o procedimentoimprime-lista-de-pares da aula passada usando o proce-dimentofor-each . Lembre-se que o procedimento recebe uma lista de pares e imprime ospares, um por linha, e deve assinalar quando é que chega ao fim da lista. Por exemplo,

(imprime-lista-de-pares (list (cons "Luisa" 12345678)(cons "Jorge" 23456789)(cons "Maria" 34567890)(cons "Rui" 45678901)))

Deverá imprimir

Luisa -> 12345678Jorge -> 23456789Maria -> 34567890Rui -> 45678901Fim da lista

Resposta:

(define (imprime-elemento el)(cond ((not (pair? el))

(error "imprime-elemento: espera um par, recebeu" el))(else (display (car el))

(display " -> ")(display (cdr el))(newline))))

(define (imprime-lista-de-pares lista)(for-each imprime-elemento lista))

Page 52: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

9 LISTAS EM SCHEME 51

Nesta definição, o fim da lista é assinalado pelo valor retornado pelo procedimentofor-each . Exem-plos:

>(imprime-lista-de-pares (list (cons "Luisa" 12345678)(cons "Jorge" 23456789)(cons "Maria" 34567890)(cons "Rui" 45678901)))

Luisa -> 12345678Jorge -> 23456789Maria -> 34567890Rui -> 45678901#t>(imprime-lista-de-pares (list (cons "Luisa" 12345678)

(cons "Jorge" 23456789)(cons "Maria" 34567890)"Rui"))

Luisa -> 12345678Jorge -> 23456789Maria -> 34567890imprime-elemento: espera um par, recebeu "Rui"

Exercício 9.8(Livro — 2.24) Suponha que avaliamos a expressão(list 1 (list 2 (list 3 4))) .Mostre o resultado impresso pelo interpretador, a estrutura de caixas e ponteiros correspondente.Resposta:

>(list 1 (list 2 (list 3 4)))(1 (2 (3 4)))

Exercício 9.9(Livro — 2.25) Apresente combinações decar s ecdr s que seleccionem o 7 de cada uma daslistas seguintes:

(1 3 (5 7) 9)

((7))

(1 (2 (3 (4 (5 (6 7))))))

Resposta:

>(car (cdaddr ’(1 3 (5 7) 9)))7>(caar ’((7)))7>(cadadr (cadadr (cadadr ’(1 (2 (3 (4 (5 (6 7)))))))))7

Exercício 9.10(Livro — 2.26) Suponha que definimosx ey como sendo duas listas:

Page 53: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

9 LISTAS EM SCHEME 52

(define x (list 1 2 3))

(define y (list 4 5 6))

Qual é o resultado impresso pelo interpretador como resposta a cada uma das seguintes expres-sões?

(append x y)

(cons x y)

(list x y)

Resposta:

>(append x y)(1 2 3 4 5 6)>(cons x y)((1 2 3) 4 5 6)>(list x y)((1 2 3) (4 5 6))

Page 54: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

10 LISTAS EM ÁRVORE EM SCHEME 53

10 Listas em árvore em Scheme

Sumário

Resumo

Page 55: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

10 LISTAS EM ÁRVORE EM SCHEME 54

Exercícios

Exercício 10.1(Livro — 2.27) Modifique o procedimentoreverse (do Livro — 2.18) para produzir um pro-cedimentodeep-reverse que recebe uma lista como argumento e retorna a lista com os seuselementos invertidos e com todas as suas sublistas tambem invertidas. Por exemplo,

(define x (list (list 1 2) (list 3 4)))

x((1 2) (3 4))

(reverse x)((3 4) (1 2))

(deep-reverse x)((4 3) (2 1))

Lembre-se que o procedimentoreverse recebe como argumento uma lista e retorna uma listacom os mesmos elementos, mas pela ordem inversa:

(define (reverse l)(define (r-aux l res)

(if (null? l)res(r-aux (cdr l) (cons (car l) res))))

(r-aux l ()))

Resposta:

(define (deep-reverse l)(cond ((null? l) ())

((pair? (car l)) (append (deep-reverse (cdr l))(list (deep-reverse (car l)))))

(else (append (deep-reverse (cdr l))(list (car l))))))

Exemplos:

>(define x (list (list 1 2) (list 3 4)))

>(deep-reverse x)((4 3) (2 1))

>(deep-reverse (list x x))(((4 3) (2 1)) ((4 3) (2 1)))

Exercício 10.2(Livro — 2.28) Escreva um procedimentofringe que recebe como argumento uma árvore(representada como uma lista de listas) e retorna uma lista cujos elementos são todas as folhasda árvore da esquerda para a direita. Por exemplo,

Page 56: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

10 LISTAS EM ÁRVORE EM SCHEME 55

(define x (list (list 1 2) (list 3 4)))

(fringe x)(1 2 3 4)

(fringe (list x x))(1 2 3 4 1 2 3 4)

Resposta:

(define (fringe l)(cond ((null? l) ())

((pair? (car l)) (append (fringe (car l))(fringe (cdr l))))

(else (cons (car l)(fringe (cdr l))))))

Exemplos:

>(define x (list (list 1 2) (list 3 4)))

>(fringe x)(1 2 3 4)

>(fringe (list x x))(1 2 3 4 1 2 3 4)

>(fringe (list 1 2 (cons 3 4) (list 5 6)))car: expects argument of type <pair>; given 4

Exercício 10.3(Livro — 2.30) Defina o procedimentosquare-tree análogo aosquare-list (do Livro— 2.18). O procedimentosquare-tree deve-se comportar da seguinte forma:

(square-tree(list 1

(list 2 (list 3 4) 5)(list 6 7)))

(1 (4 (9 16) 25) (36 49))

Deve definir este procedimento directamente (isto é, sem usar procedimentos de ordem superior)e também usando o procedimentomap.Resposta:

(define (square-tree l)(cond ((null? l) ())

((pair? (car l)) (cons (square-tree (car l))(square-tree (cdr l))))

(else (cons (square (car l))(square-tree (cdr l))))))

(define (square x)( * x x))

Page 57: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

10 LISTAS EM ÁRVORE EM SCHEME 56

Exemplos:

>(square-tree(list 1

(list 2 (list 3 4) 5)(list 6 7)))

(1 (4 (9 16) 25) (36 49))

Usando o procedimentomap, ficaria:

(define (square-tree-com-map tree)(map (lambda (x)

(if (pair? x)(square-tree-com-map x)(square x)))

tree))

Exemplos:

>(square-tree-com-map(list 1

(list 2 (list 3 4) 5)(list 6 7)))

(1 (4 (9 16) 25) (36 49))

Exercício 10.4(Livro — 2.31) Abstraia a sua resposta ao exercício anteriorpara produzir um procedimentotree-map , com a propriedade quesquare-tree poderia ser definido como:

(define (square-tree tree)(tree-map square tree))

Resposta:

(define (tree-map proc tree)(cond ((null? tree) ())

((pair? (car tree)) (cons (tree-map proc (car tree))(tree-map proc (cdr tree))))

(else (cons (proc (car tree))(tree-map proc (cdr tree))))))

(define (square-tree tree)(tree-map square tree))

Exemplos:

>(square-tree(list 1

(list 2 (list 3 4) 5)(list 6 7)))

(1 (4 (9 16) 25) (36 49))

Page 58: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

10 LISTAS EM ÁRVORE EM SCHEME 57

Exercício 10.5(Livro — 2.32) Podemos representar um conjunto como uma lista de elementos distintos, epodemos representar o conjunto de todos os subconjuntos de um conjunto como uma lista delistas. Por exemplo, se o conjunto é(1 2 3) , então o conjunto de todos os seus subconjuntosé (() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3)) . Complete a seguinte definiçãode um procedimento que gera o conjunto dos subconjuntos de umconjunto e dê uma explicaçãoclara de porque é que ele funciona.

(define (subsets s)(if (null? s)

(list ())(let ((rest (subsets (cdr s))))

(append rest (map <??> rest)))))

Resposta:

(define (subsets s)(if (null? s)

(list ())(let ((rest (subsets (cdr s))))

(append rest (map (lambda (x) (cons (car s) x)) rest)))))

Exemplos:

>(subsets (list 1 2 3))(() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3))

Page 59: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

11 MAIS EXERCÍCIOS SOBRE LISTAS 58

11 Mais exercícios sobre listas

Sumário

Resumo

Page 60: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

11 MAIS EXERCÍCIOS SOBRE LISTAS 59

Exercícios

Exercício 11.1Considere que foi definido o tipo árvore binária. Para este tipo, estão definidas as operações:

• constroi-arvore que recebe a raiz, a árvore esquerda e a árvore direita e constrói aárvore correspondente.

• arvore-raiz que recebe uma árvore binária e retorna a sua raiz.

• arvore-esquerda que recebe uma árvore binária e retorna a sua árvore esquerda.

• arvore-direita que recebe uma árvore binária e retorna a sua árvore direita.

• arvore-vazia? que recebe um objecto e retorna verdadeiro se ele corresponder a umaárvore vazia e falso caso contrário.

Com base nas operações descritas, escreva os seguintes procedimentos para percorrer árvoresbinárias:

1. percorre-inorder recebe uma árvore binária e retorna uma lista com todas as suafolhas, percorrendo primeiro a árvore esquerda, depois a raiz e depois a árvore direita daárvore inicial.

2. percorre-preorder recebe uma árvore binária e retorna uma lista com todas as suafolhas, percorrendo primeiro a raíz, depois a árvore esquerda e depois a árvore direita daárvore inicial.

3. percorre-posorder recebe uma árvore binária e retorna uma lista com todas as suafolhas, percorrendo primeiro a árvore esquerda, depois a árvore direita e depois a raiz daárvore inicial.

Resposta:

Exercício 11.2Uma árvore binária de procura é uma árvore binária em que todos os elementos que estão na suaárvore esquerda são menores que a raiz e todos os elementos que estão na sua árvore direita sãomaiores que a raiz.Com base nas operações definidas no exercício anterior, escreva os seguintes procedimentos:

1. insere-elemento que recebe um elemento e uma árvore binária de procura e o inserena árvore.

2. ordena-lista que recebe uma lista de elementos e retorna uma nova lista comoselementos ordenados.

Resposta:

Exercício 11.3Escreva um procedimentofiltra que recebe um predicado e uma lista e retorna uma lista quecontém apenas os elementos da lista inicial que satisfazem opredicado. Por exemplo:

Page 61: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

11 MAIS EXERCÍCIOS SOBRE LISTAS 60

(filtra even? (list 1 2 3 4 5))(2 4)

(filtra even? (list 1 3 5 7))()

Resposta:

(define (filtra pred lst)(cond ((null? lst) ())

((pred (first lst))(cons (first lst)

(filtra pred (rest lst))))(else (filtra pred (rest lst)))))

Exercício 11.4Escreva um procedimentotodos? que recebe um predicado e uma lista e retorna verdadeiro setodos os elementos da lista satisfizerem o predicado e falso caso contrário. Por exemplo:

(todos? even? (list 1 2 3 4 5))#f

(todos? even? (list 2 4 6))#t

Resposta:

(define (todos? pred lst)(cond ((null? lst) #t)

((pred (first lst))(todos? pred (rest lst)))

(else #f)))

Exercício 11.5Escreva um procedimentoalgum? que recebe um predicado e uma lista e retorna verdadeiro sealgum dos elementos da lista satisfizer o predicado e falso caso contrário. Por exemplo:

(algum? odd? (list 1 2 3 4 5))#t

(algum? odd? (list 2 4 6))#f

Resposta:

(define (algum? pred lst)(cond ((null? lst) #f)

((pred (first lst)) #t)(else (algum? pred (rest lst)))))

Page 62: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

11 MAIS EXERCÍCIOS SOBRE LISTAS 61

Exercício 11.6Escreva um procedimentosubstitui que recebe dois elementos e uma lista e retorna umaoutra lista que resulta de substituir todas as ocorrências do primeiro elemento pelo segundo nalista inicial. Por exemplo:

(substitui 2 3 (list 1 2 3 2 5))(1 3 3 3 5)

(substitui 2 3 (list 1 3 5 7))(1 3 5 7)

Resposta:

(define (substitui velho novo lst)(cond ((null? lst) ())

((= (first lst) velho)(cons novo

(substitui velho novo (rest lst))))(else (cons (first lst)

(substitui velho novo (rest lst))))))

Exercício 11.7Escreva um procedimentofold-right que recebe um procedimento de dois argumentos, ovalor inicial de um acumulador e uma lista e retorna o resultado de aplicar o procedimento aoelemento inicial e ao resultado de aplicar o procedimento a todos os elementos que estão à suadireita. Quando a lista for vazia, este procedimento deve retornar o valor inicial. Por exemplo:

(fold-right + 0 (list 1 2 3 4))10

(fold-right + 0 ())0

Resposta:

(define (fold-right proc inicial lst)(if (null? lst)

inicial(proc (first lst)

(fold-right proc inicial (rest lst)))))

Exercício 11.8Com base no procedimentofold-right escreva os seguintes procedimentos:

1. multiplica-lista que recebe uma lista e retorna o produto de todos os seus elemen-tos.

2. maximo-lista que recebe uma lista e retorna o maior dos seus elementos.

3. inverte-lista que recebe uma lista e retorna outra lista com os elementos dalistainicial pela ordem inversa.

Page 63: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

11 MAIS EXERCÍCIOS SOBRE LISTAS 62

4. junta-listas que recebe duas listas e retorna outra lista que resulta de juntar as duas.

Resposta:

1. (define (multiplica-lista lst)(if (null? lst)

(error "multiplica-lista: espera uma lista com pelo menos1 elemento, recebeu" lst)

(fold-right * 1 lst)))

(multiplica-lista (list 1 2 3 4))24

(multiplica-lista ())multiplica-lista: espera uma lista com pelo menos 1 elemento, recebeu ()

2. (define (maximo-lista lst)(if (null? lst)

(error "maximo-lista: espera uma lista com pelo menos 1 elem ento,recebeu" lst)

(fold-right max (first lst) (rest lst))))

(maximo-lista (list 1 2 3 4))4

(maximo-lista ())maximo-lista: espera uma lista com pelo menos 1 elemento, recebeu ()

3. (define (inverte-lista lst)(fold-right (lambda (x y) (append y (list x))) () lst))

(inverte-lista (list 1 2 3 4))(4 3 2 1)

(inverte-lista ())()

4. (define (junta-listas lst1 lst2)(fold-right cons lst2 lst1))

(junta-listas (list 1 2 3 4) (list 5 6 7))(1 2 3 4 5 6 7)

(junta-listas () (list 5 6 7))(5 6 7)

Exercício 11.9Uma forma de compactar listas de números é, dada uma lista de números (possivelmente re-petidos), transformá-la numa lista em que ocorrências consecutivas de um mesmo número sãosubstituídas por um par, em que o primeiro elemento é o númerode vezes que o número aparecerepetido e o segundo elemento é o número.Escreva o procedimentorun-length-encode que compacta listas de inteiros. Por exemplo,

Page 64: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

11 MAIS EXERCÍCIOS SOBRE LISTAS 63

(run-length-encode ’(1 1 1 1 1 1 1 2 3 3 3 3 4 4 4 4 1 3 3 3 3))((7 . 1) 2 (4 . 3) (4 . 4) 1 (4 . 3))

(run-length-encode ’(1 2 1 2 3 3 3 3 4 4 4 4 1 1 3 3 3 3 3))(1 2 1 2 (4 . 3) (4 . 4) (2 . 1) (5 . 3))

Repare que as sequências de apenas um elemento não são substituidas.

Depois de ter uma lista compactada, pode ser necessário saber qual era a lista original. Escrevao procedimentorun-length-decode que, dada uma lista de inteiros compactada, retorna alista original. Por exemplo,

(run-length-decode ’((7 . 1) 2 (4 . 3) (4 . 4) 1 (4 . 3)))(1 1 1 1 1 1 1 2 3 3 3 3 4 4 4 4 1 3 3 3 3)

(run-length-decode ’(1 2 1 2 (4 . 3) (4 . 4) (2 . 1) (5 . 3)))(1 2 1 2 3 3 3 3 4 4 4 4 1 1 3 3 3 3 3)

Resposta:

(define (run-length-encode lst)(define (encode-seq lst last count)

(define (make-code last count)(if (> count 1)

(cons count last)last))

(cond ((null? lst) (list (make-code last count)))((= last (first lst))

(encode-seq (rest lst) last (add1 count)))(else (cons (make-code last count)

(encode-seq (rest lst)(first lst)1)))))

(if (null? lst)()(encode-seq (rest lst) (first lst) 1)))

(define (run-length-decode encoded-lst)(define (decode code)

(define (make-list count elem)(if (zero? count)

()(cons elem (make-list (sub1 count) elem))))

(if (pair? code)(make-list (car code) (cdr code))(list code)))

(if (null? encoded-lst)()(append (decode (first encoded-lst))

(run-length-decode (rest encoded-lst)))))

Page 65: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

12 QUOTE 64

12 Quote

Sumário

Resumo

Page 66: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

12 QUOTE 65

Exercícios

Exercício 12.1(Livro — exemplo das páginas 143-4) Considere que foram feitas as definições:

(define a 1)(define b 2)

Diga qual o valor de cada uma das seguintes expressões:

(list a b)(list ’a ’b)(list ’a b)(first ’(a b c))(rest ’(a b c))

Resposta:

(list a b)(1 2)

(list ’a ’b)(a b)

(list ’a b)(a 2)

(first ’(a b c))a

(rest ’(a b c))(b c)

Exercício 12.2(Livro — exemplo da página 144) Defina o procedimentomemq, que recebe um símbolo e umalista e retorna falso se o símbolo não estiver contido na lista (isto é, não foreq? a nenhum doselementos da lista) e a sublista que começa com a primeira ocorrência do símbolo na lista casocontrário. Por exemplo,

(memq ’apple ’(pear banana prune))#f

(memq ’apple ’(x (apple sauce) y apple pear))(apple pear)

Resposta:

(define (memq item lst)(cond ((null? lst) #f)

((eq? item (first lst)) lst)(else (memq item (rest lst)))))

Page 67: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

12 QUOTE 66

Exercício 12.3(Livro — 2.53) O que é que o interpretador de Scheme imprime como resposta à avaliação decada uma das seguintes expressões:

(list ’a ’b ’c)(list (list ’george))(cdr ’((x1 x2) (y1 y2)))(cadr ’((x1 x2) (y1 y2)))(pair? (car ’(a short list)))(memq ’red ’((red shoes) (blue socks)))(memq ’red ’(red shoes blue socks))

Resposta:

(list ’a ’b ’c)(a b c)

(list (list ’george))((george))

(cdr ’((x1 x2) (y1 y2)))((y1 y2))

(cadr ’((x1 x2) (y1 y2)))(y1 y2)

(pair? (car ’(a short list)))#f

(memq ’red ’((red shoes) (blue socks)))#f

(memq ’red ’(red shoes blue socks))(red shoes blue socks)

Exercício 12.4(Livro — 2.54) Duas listas sãoequal? se contiverem elementos iguais e estes estiverem pelamesma ordem. Por exemplo,

(equal? ’(this is a list) ’(this is a list))

é verdade, mas

(equal? ’(this is a list) ’(this (is a) list))

é falso. Para sermos mais precisos, podemos definirequal? recursivamente em termos daigualdade básica entre símboloseq? , dizendo quea eb sãoequal? se forem ambos símbolose foremeq? ou forem ambos listas em que(first a) é equal? a (first b) e (resta) éequal? a (rest b) . Usando esta ideia, implementeequal? como um procedimento.Resposta:

Page 68: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

12 QUOTE 67

(define (equal? l1 l2)(cond ((and (number? l1) (number? l2)) (= l1 l2))

((and (symbol? l1) (symbol? l2)) (eq? l1 l2))((and (null? l1) (null? l2)) #t)((or (atom? l1) (atom? l2)) #f)(else (and (equal? (first l1) (first l2))

(equal? (rest l1) (rest l2))))))

(equal? ’(this is a list) ’(this is a list))#t

(equal? ’(this is a list) ’(this (is a) list))#f

(equal? ’(2 3 a 4) ’(2 3 a 4))#t

(equal? ’(2 3 a 4) ’(2 3))#f

Exercício 12.5(Livro — 2.55) O resultado de avaliar a expressão

(first ’’abracadabra)

équote . Explique porquê.Resposta:A expansão de(first ”abracadabra) é(first (quote (quote abracadabra))) .

Para avaliar a segunda expressão:

1. Avaliamos o operador. Neste caso,first , que tem como resultado o procedimento que dado umalista retorna o seu primeiro argumento.

2. Avaliamos os seus argumentos, por qualquer ordem. Neste caso, avaliar a expressão(quote (quote abracadabra)) tem como resultado a lista(quote abracadabra) .

3. Aplicamos o operador aos valores dos argumentos e retornamos o resultado. Neste caso, aplicar oprocedimentofirst à lista(quote abracadabra) tem como resultado o primeiro elementoda lista, que é o símboloquote .

Page 69: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

13 MODULARIDADE, OBJECTOS E ESTADO 68

13 Modularidade, objectos e estado

Sumário

Resumo

Page 70: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

13 MODULARIDADE, OBJECTOS E ESTADO 69

Exercícios

Exercício 13.1Diga o que é impresso pelo interpretador de Scheme ao avaliarcada uma das seguintes expres-sões:

(define a 3)

(set! a "ola")

(+ a 1)

(begin(let ((a 5))

(+ a ( * 45 327))(sqrt (length ’(1 a b "bom dia" (2 5) 3))))

(display ’a)a)

(set! c 78)

Resposta:

>(define a 3)

>(set! a "ola")

>(+ a 1)+: expects type <number> as 1st argument, given: "ola"; other arguments were: 1

>(begin(let ((a 5))

(+ a ( * 45 327))(sqrt (length ’(1 a b "bom dia" (2 5) 3))))

(display ’a)a)

a"ola"

>(set! c 78)set!: cannot set undefined identifier: c

Exercício 13.2(Livro — 3.1) Um acumulador é um procedimento que é chamado repetidamente com apenas umargumento numérico e acumula os seus argumentos numa soma. De cada vez que é chamado,retorna a soma acumulada até ao momento.Escreva um procedimentomake-accumulator que gera acumuladores, cada um dos quaismantendo uma soma independente. O valor de entrada para o procedimentomake-accumulatordeve especificar o valor inicial da soma. Por exemplo,

Page 71: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

13 MODULARIDADE, OBJECTOS E ESTADO 70

(define A (make-accumulator 5))

(A 10)15

(A 10)25

Resposta:

(define (make-accumulator init)(lambda (num)

(set! init (+ init num))init))

Exercício 13.3(Livro — 3.2) Em aplicações para testar software, é útil ser capaz de contar o número de vezesque um procedimento é chamado durante o decurso de uma computação.Escreva um procedimentomake-monitored que recebe um procedimentof como argumento,que por sua vez é um procedimento de um argumento. O resultadoretornado pelo procedimentomake-monitored é um terceiro procedimentomf que mantém um registo do número de vezesque foi chamado através de um contador interno. Se o valor de entrada paramf for o símbolohow-many-calls? , entãomf deve retornar o valor do contador. Se o valor de entrada for osímboloreset-count , entãomf deve inicializar o contador a zero. Para qualquer outro valorde entrada,mf retorna o valor de aplicarf a esse valor e incrementa o contador. Por exemplo,podemos criar uma versão monitorizada do procedimentosqrt :

(define s (make-monitored sqrt))

(s 100)10

(s ’how-many-calls?)1

Resposta:

(define (make-monitored proc)(let ((calls 0))

(lambda (input)(cond ((eq? input ’how-many-calls?) calls)

((eq? input ’reset-count) (set! calls 0))(else (set! calls (add1 calls))

(proc input))))))

Exercício 13.4Desenhe o diagrama dos ambientes criados pelos seguintes exemplos de código:

Page 72: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

13 MODULARIDADE, OBJECTOS E ESTADO 71

1. (define x 63)

(define square(lambda (x)

( * x x)))

(define sum-sq(lambda (x y)

(+ (square x) (square y))))

(sum-sq 3 4)

O resultado é 25.

2. (define (make-adder n)(lambda (x) (+ x n)))

(define addthree (make-adder 3))

(define addfive (make-adder 5))

(addfive 7)

(addthree 7)

3. Os ambientes permitem-nos perceber como é que podemos usar procedimentos como re-presentações para tipos abstractos de dados. Por exemplo, podemos criar rectângulos daseguinte forma:

(define (make-rect w h)(define (dispatch op)

(cond ((eq? op ’width) w)((eq? op ’height) h)((eq? op ’area) ( * w h))((eq? op ’perimeter) ( * 2 (+ w h)))(else (error "rectangle: non-existent operation" op))))

dispatch)

(define r1 (make-rect 5 30))

(r1 ’height)

Resposta:

Exercício 13.5Introduzir a forma especialset! na nossa linguagem obriga-nos a pensar no significado deigualdade e mudança. Dê exemplos de procedimentos simples que sejam:

1. Um procedimento referencialmente transparente

Page 73: Ana Cardoso Cachopo Ano Lectivo 1998/1999 - web.ist.utl.ptweb.ist.utl.pt/acardoso/docs/1998-ip-guiaPraticas.pdf · CONTEÚDO 1 Conteúdo 1 Apresentação 2 2 Os elementos da programação

13 MODULARIDADE, OBJECTOS E ESTADO 72

2. Um procedimento referencialmente opaco (não transparente)

Resposta:

1. (define (soma-transparente inicial)(lambda (num)

(+ inicial num)))

(define st1 (soma-transparente 25))

(define st2 (soma-transparente 25))

(st1 20)45

(st1 20)45

(st2 20)45

Neste caso, podemos dizer quest1 e st2 são iguais, pois um pode ser substituido pelo outro emqualquer lugar da computação sem alterar o resultado. Uma linguagem que suporta o conceito deque “iguais podem ser substituidos por iguais” numa expressão sem alterar o valor da expressãodiz-sereferencialmente transparente.

2. A transparência referencial é violada quando introduzimos set! na linguagem, o que dificulta averificação de quando é que podemos simplificar expressões substituindo-as por outras equivalen-tes.

(define (soma-opaco inicial)(lambda (num)

(set! inicial (+ inicial num))inicial))

(define so1 (soma-opaco 25))

(define so2 (soma-opaco 25))

(so1 20)45

(so1 20)65

(so2 20)45