• Nenhum resultado encontrado

Aulas práticas da cadeira de Introdução à Programação

N/A
N/A
Protected

Academic year: 2021

Share "Aulas práticas da cadeira de Introdução à Programação"

Copied!
73
0
0

Texto

(1)

Aulas práticas da cadeira de

Introdução à Programação

Ana Cardoso Cachopo

(2)

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 recursivos

Recursão em árvores 19

6 Ordens de crescimento

Procedimentos de ordem superior 23

7 Métodos gerais: procedimentos que retornam procedimentos 31 8 Abstracção de dados

Pares 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

(3)

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. Verhttp://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

– Ensinamos programaçã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 trabalhar e 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 news

ist.cadeiras.leic.ip – Endereço de correio electrónico

(4)

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 construir procedimentos simples.

(5)

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 resultado impresso pelo interpretador de Scheme quando é avaliada cada uma dessas expressões. Assuma que 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))) b a) (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: > 10 10 > (+ 5 3 4) 12

(6)

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))) b a) 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: (/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5))))) (* 3 (- 6 2)

(7)

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.3

Defina um procedimento que calcula o volume de uma esferav = 4 3πr

3. 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 a soma 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 forem 4, 4 e 3, não funciona.

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

(if (> a c) a

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

b c)))

(8)

2 OS ELEMENTOS DA PROGRAMAÇÃO 7 (define (max a b) (if (> a b) a b)) (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) c a)) (if (> a c) a (if (> b c) c b)))) (define (sum-of-squares-of-larger-two a b c)

(9)

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 rudimentos sobre a utilização do sistema operativo UNIX, bem como a utilização do editor de texto emacs, que pode também servir para ler mail e news.

A primeira metade deve ser passada numa sala normal (com quadro) e deve ser apresentado o modo de interagir com o sistema operativo, o conceito de ficheiro, directoria e os rudimentos de ediçã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-ip

Password:

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 passwd

passwd: Changing password for ic-ip Enter login password:

New password:

Password is too short - must be at least 6 characters. New password:

(10)

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 logout

ic-ip@camoes logged out at Mon Sep 29 18:53:24 WET DST 1997

• Sintaxe dos comandos em UNIX

comando [-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 directorias

pwd Mostra a directoria corrente

mkdir nomeDir Cria uma directoria chamadanomeDir rmdir nomeDir Remove a directorianomeDir, se estiver vazia

cd [nomeDir] Muda para a directorianomeDir ls Lista os ficheiros da directoria corrente

• Manipular ficheiros

cp nomeFichVelho nomeFichNovo

CopianomeFichVelhoparanomeFichNovo

cp nomeFich* nomeDir

Copia um conjunto de ficheiros para a directorianomeDir

mv nomeFichVelho nomeFichNovo

Muda o nome denomeFichVelhoparanomeFichNovo

mv nomeFich* nomeDir

Move um conjunto de ficheiros paranomeDir

mv nomeDirVelho nomeDirNovo

Move 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 esses caracteres 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 primeirasnlinhas de um conjunto de ficheiros

tail -n nomeFich*

Mostra as últimasnlinhas de um conjunto de ficheiros

(11)

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 que estão naimpressora

lprm [-P impressora] job* userId*

Cancela todos os ´jobs´ especificados e/ou os ´jobs´ dos utilizadores especificados que estão naimpressora

• Mudar as permissões de um ficheiro

ls -l nomeFich

Para 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: SujeitoSinalValor Sujeito u, g, o, a

Sinal +, -, = 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, onde modoé um número em octal

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

man palavra

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

man -k palavra

Mostra as entradas do manual que contêmpalavra

Exemplos:man -k mode,man chmod

• Utilização do Mail

mailx endereco

Envia uma mensagem para enderecoa partir da ´shell´ do UNIX.ctrl-dsignifica end-of-file

mailx [-f nomeFich] [endereco]*

Envia o ficheironomeFichparaendereco

mailx

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

• Caracteres especiais importantes

ctrl-d End-Of-File - indica o fim de um ficheiro

ctrl-c Interrupt - termina o processo que está a ser executado

(12)

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

• Redirecionamento de entrada e saída

< nomeFich

redirecciona o dispositivo de entrada standard para nomeFich Permite usar o conteúdo de um ficheiro como entrada para um processo

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

• Internet

ist.cadeiras.leic.ip

News — 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/ip

WWW — página da cadeira de IP (lynx,netscape,internet explorer)

• Manipular processos

ps Mostra os processos do utilizador

kill numProcesso Mata processos do utilizador

bg [numProcesso] Passa um processo do utilizador para ´background´

fg [numProcesso] Passa um processo do utilizador para ´foreground´

& Executa um processo do utilizador em ´background´

• Nocamoes

setenv DISPLAY xxx:0

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

emacs -font fixed

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

• Oemacs

Oemacsé um editor de texto.

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

Oemacstem ajuda e documentação disponível no menu Help, que pode ser utilizada para aprender a trabalhar com ele.

(13)

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

Exercícios

Exercício 3.1

Escreva em Scheme os seguintes procedimentos:

• Um procedimento chamadohipotenusaque, dados os comprimentos dos dois catetos de um triângulo rectângulo, calcula o comprimento da hipotenusa. Dados os comprimentos dos catetosa e b do triângulo, a hipotenusa h é calculada como: h = √a2+ b2

• Um procedimento chamadoperimetroque, dados os comprimentos dos dois catetos de um 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 ficheiro de texto, 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 o seguinte comando:/users/cadeiras/ic-ip/entrega-tpc

Este comando irá pedir o número de aluno e o nome do ficheiro onde se encontra o TPC, enviando de 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 por correio 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:

(14)

4 RECURSÃO 13

4

Recursão

Sumário O objectivo desta aula é que os alunos aprendam a construir procedimentos recursivos e que se apercebam de como é que a recursão pode ser utilizada para implementar repetição. Resumo Um procedimento recursivo é um procedimento definido à custa de si próprio, isto é, que se chama a si mesmo.

(15)

4 RECURSÃO 14

Exercícios

Exercício 4.1

Defina um procedimento que calcula uma potência inteira dex. Note que xn = x∗xn−1ex0 = 1. Resposta: (define (potencia x n) (if (= n 0) 1 (* x (potencia x (- n 1))))) Exercício 4.2

Considere definidos os seguintes procedimentos: add1, sub1 e zero?, que somam um ao seu 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 zeroxey, e calcula a soma entre eles.

2. O procedimentoigual?, que dados dois inteiros superiores ou iguais a zeroxey, retorna verdadeiro se eles forem iguais e falso caso contrário.

3. O procedimentomenor?, que dados dois inteiros superiores ou iguais a zeroxey, indica sexé menor quey.

4. O procedimentoproduto, que calcula o produto entre dois inteiros superiores ou iguais a zeroxey. 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

(16)

4 RECURSÃO 15 Exercício 4.3

O número de combinações dem objectos n a n 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) se m > n, m > 0 e n > 0. Escreva um procedimento que calcula o número de combinações de m objectos n a n. Use a estrutura 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úmeros diferentes, calcule o número de chaves existentes.

Sabendo que cada aposta custa 40$00, quanto dinheiro teria que gastar para ter a certeza que 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 algum tempo) O resutado deverá ser13983816.

Para saber quanto dinheiro se tem que gastar, basta multiplicar este valor por 40$00, que é quanto custa cada 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 a existência de combinações cu-jos operadores são expressões compostas. Use esta observação para descrever o comportamento do seguinte procedimento:

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

Resposta: Este procedimento somaacom o modulo deb, pois o operador utilizado é+ou-, conforme

bseja 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 se deparou usa avaliação pela ordem aplicativa ou avaliação pela ordem normal. Ele define os dois procedimentos:

(17)

4 RECURSÃO 16 (define (p) (p)) (define (test x y) (if (= x 0) 0 y))

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 observar com um interpretador que use a ordem de avaliação normal? Explique a sua resposta. (Assuma que a regra de avaliação para a forma especialifé a mesma, quer o interpretador use a ordem de avaliação aplicativa, quer use a ordem de avaliação normal: primeiro avalia o predicado e o resultado determina se deve avaliar o consequente ou a alternativa.)

Resposta: Num Scheme que use a ordem aplicativa, como é o caso do que estamos a usar, os argumentos

são avaliados antes de se aplicar o operador. Assim, para avaliar(test 0 (p)), começa-se por ava-liar as sub-expressõestest,0e(p)e só depois é que se aplica o operador (resultante da avaliação de

test). Por isso, e uma vez quepcorresponde a um ciclo infinito, a avaliacao de(test 0 (p))não vai terminar.

Num Scheme que use a ordem de avaliação normal (“fully expand and 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 especialifaos seus argumentos. Neste caso, como a condição doif (= 0 0)tem o 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 oifprecisa de ser uma forma especial. “Porque é que não o posso definir como um procedimento normal em termos docond?” 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-ifpara re-escrever o programa da raíz quadrada: (define (improve guess x)

(18)

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 ter

que avaliar os seus argumentos. Assim, quando queremos executar o procedimento sqrt-iter, vamos ter que avaliar um new-if, que por sua vez vai ter que avaliar todos os seus argumentos, incluindo uma nova chamada a sqrt-iter, que por sua vez corresponde à avaliacao de 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 funcionar muito bem para raízes de números muito pequenos. Para além disso, nos computadores reais as operações aritméticas são quase sempre efectuadas com precisão limitada. Este facto torna o nosso teste inadequado para números muito grandes. Explique estas afirmações, com exemplos que mostrem como é que o teste falha para números muito pequenos e muito grandes. Uma estratégia alternativa para implementar o good-enough? é observar como é que o guess muda de uma iteração para a próxima e parar quando a mudança é uma fracção pequena do guess. Escreva um procedimento para calcular raízes quadradas que use este tipo de teste de terminaçã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 que calcula raízes quadradas.

Resposta:

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

(* 2 guess)) 3))

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

(19)

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.9

Escreva 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 que devem 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)))))

(20)

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

5

Processos iterativos vs recursivos

Recursão em árvores

Sumário O objectivo desta aula é que os alunos aprendam a construir e distinguir entre processos iterativos e recursivos.

Para além disso, devem também dominar a recursão em ávores. Resumo

(21)

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

Exercícios

Exercício 5.1

O número de combinações dem objectos n a n 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) se m > n, m > 0 e n > 0. 1. Escreva um procedimento que calcula o número de combinações dem objectos n a n. Use

a estrutura de blocos para garantir que o seu procedimento recebe sempre os argumentos correctos: inteiros superiores ou iguais a zero em ≥ n.

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

3. Sabendo que cada aposta custa 40$00, quanto dinheiro teria que gastar para ter a certeza que 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 algum tempo) O resutado deverá ser13983816.

Para saber quanto dinheiro se tem que gastar, basta multiplicar este valor por 40$00, que é quanto custa cada 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 dois inteiros positivos em termos dos procedimentosinc, que incrementa o seu argumento de uma unidade, 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?

(22)

5 PROCESSOS ITERATIVOS VS RECURSIVOS RECURSÃO EM ÁRVORES 21 Exercício 5.3

Defina um procedimento que calcula uma potência inteira de x 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 em que 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 um argumento 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, e chamar 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.4

Com base em somas e subtrações, defina o procedimentoproduto, que calcula o produto entre dois inteiros superiores ou iguais a zeroxey.

1. Usando um processo recursivo 2. Usando um processo iterativo

Resposta: Usando um processo recursivo, fica: (define (produto x y)

(if (zero? y) 0

(23)

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))

(24)

6 ORDENS DE CRESCIMENTO PROCEDIMENTOS DE ORDEM SUPERIOR 23

6

Ordens de crescimento

Procedimentos de ordem superior

Sumário Resumo

(25)

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 a aproximação sinx ≈ x se x for suficientemente pequeno, e a identidade trigonométrica

sinx = 3 sin x

3 − 4 sin 3x

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 de a) usados

pelo processo gerado pelo procedimentosinequando avaliamos(sine a)?

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

ficaria:

(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···)))))

(26)

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 as suas chamadas: vamos dividindo o argumento do procedimento por três até o resultado ser menor que 0.1.

Portanto, estamos interessados em saber quantas vezes é que temos que dividir o argumento por três até que o resultado seja menor que 0.1.

Ou seja, estamos interessados em resolver a seguinte inequação em ordem a n: 3an ≤ 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 de Log310a.

Exercício 6.2

(Livro — 1.29) A Regra de Simpson é um método para fazer integração numérica. Usando a Regra de Simpson, o integal de uma funçãof entre a 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 par n, e yk = f (a + kh). (Aumentar o n aumenta a precisão da aproximação.) Defina um procedimento que recebe como argumentosf , a, b e n e retorna o valor do integral, calculado usando a Regra de Simpson. Use o seu procedimento para integrar o procedimentocuboentre0 e 1 (com n = 100 e n = 1000), e compare os resultados com os do procedimentointegralapresentado 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 procedimentosumapresentado acima gera recursão linear. No entanto, pode ser escrito de forma a gerar um processo iterativo. Mostre como é que isso poderia ser feito preenchendo as expressões que faltam na definição que se segue:

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

(if <??> <??>

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

(27)

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 procedimento sumé apenas o mais simples de um vasto número de abstracções seme-lhantes, que podem ser capturadas como procedimentos de ordem superior. Escreva um procedimento análogo chamadoproduct, que retorna o produto dos valores de uma fun-ção para pontos pertencentes a um intervalo. Mostre como definir o factorial em termos doproduct. Use também o productpara calcular aproximações deπ usando a fórmula

π 4 =

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

2. Se o seu procedimento productgerar um processo recursivo, escreva um que gere um processo 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 oproductpara 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 atingem falores muito altos e fazem overflow.

(28)

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 que sum eproductsão ambos casos especiais de uma noção ainda mais geral chamada accumulate, que combina uma coleção de termos, usando uma função de acumulação geral:

(accumulate combiner null-value term a next b)

Accumulaterecebe como argumentos o mesmoterm e as mesmas especificações do intervaloaeb, bem como um procedimentocombiner(de 2 argumentos) que especifica como é 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 procedimentoaccumulatee mostre como é quesumeproductpodem ser definidos como simples chamadas aaccumulate.

2. Se o seu procedimentoaccumulategerar um processo recursivo, escreva um que gere um processo iterativo. Se gerar um processo iterativo, escreva um que gere um processo recursivo.

Resposta:

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

(29)

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)

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

Exercício 6.7

1. Escreva um procedimento que faz a composição de procedimentos. Por exemplo, a cha-mada(compoe f g x)aplica o procedimentofao resultado de aplicar o procedimento gax.

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)))

(30)

6 ORDENS DE CRESCIMENTO PROCEDIMENTOS DE ORDEM SUPERIOR 29

2. (define (triplo-fact x)

(compoe (lambda (x) (* x 3)) fact x)) Exercício 6.8

Com 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úmero n 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)))))) 1 add1 n)))

Outra possibilidade para definir o procedimentoseno-com-sumseria definir um procedimento auxiliar chamado, por exemplo, term. Tanto no caso de usarmos a lambda como no caso do procedimento auxiliar, temos que nos lembrar que osumrecebe um procedimento de um argumento. Por isso, mesmo que quiséssemos, por questão de clareza incluir mais argumentos, neste caso isso não seria possível. Com o procedimento auxiliar,seno-com-sumficaria:

(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)))

(31)

6 ORDENS DE CRESCIMENTO PROCEDIMENTOS DE ORDEM SUPERIOR 30 Exercício 6.9

Suponha que tem definido o procedimentocomb, que recebe dois inteiros maiores ou iguais a zero,men, e calcula o número de combinações demelementosnan.

Sabendo que existem 49 números possíveis para o totoloto e que cada chave tem 6 números diferentes, escreva um procedimento que escreve quanto dinheiro tem que ser gasto para ter a certeza de ganhar o primeiro prémio do totoloto, se as apostas custassem 40$00, 50$00 ou 60$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))))

(32)

7 MÉTODOS GERAIS: PROCEDIMENTOS QUE RETORNAM PROCEDIMENTOS 31

7

Métodos gerais: procedimentos que retornam

procedimen-tos

Sumário Resumo

(33)

7 MÉTODOS GERAIS: PROCEDIMENTOS QUE RETORNAM PROCEDIMENTOS 32

Exercícios

Exercício 7.1

Considere 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 e esse número:(1 + (1 + 2) + (1 + 2 + 3) + (1 + 2 + 3 + 4) + (1 + 2 + 3 + 4 + 5))

Exercício 7.2

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

1. Escreva um procedimentocalc-exprque 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 procedimento cubo, se for definido, deve ser definido dentro do procedimento calc-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)

(34)

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 no procediargu-mento exterior. Faria sentido usar a estrutura de blocos se o procedimento fosse recursivo, para evitar a repetição do teste a cada iteração.

(b) É verdade que convém utilizar a forma especiallet, pois assim podemos guardar o valor de

x!, que de outra forma teria que ser calculado duas vezes.

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

(d) Tal como já dissémos, o procedimentocubopode 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 um argumento e retorna um procedimento que aplica duas vezes o procedimento original.

Por exemplo, seadd1for um procedimento que adiciona 1 ao seu argumento, então(double add1)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 cada uma destas expressões:

((double add1) 5)

(35)

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.4

1. (Livro — 1.42) Sejam f e g duas funções de um argumento. A composição f depois de g é definida como sendo a função x 7→ f(g(x)). Defina um procedimentocomposeque implementa a composição. Por exemplo, seincfor um procedimento que adiciona 1 ao seu argumento,

((compose square inc) 6) 49

2. Compare o procedimentocomposecom o procedimentocompoeda aula passada. Por-que é Por-que eles são diferentes?

Resposta:

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

2. O procedimento compoe da aula passada recebia os procedimentos a compor e também os ar-gumentos desses procedimentos. Retornava o resultado da aplicação dos procedimentos ao valor recebido.

O procedimentocomposerecebe apenas os procedimentos e retorna outro procedimento.

O resultado do procedimentocomposepode ser usado como primeiro elemento de uma expressão em Scheme e o resultado do procedimentocompoenão.

(36)

7 MÉTODOS GERAIS: PROCEDIMENTOS QUE RETORNAM PROCEDIMENTOS 35 Exercício 7.5

(Livro — 1.43) Se f for uma função numérica e n um inteiro positivo, então podemos for-mar a n-ésima repetição da aplicação de f , que é definida como a função cujo valor em x é f (f (. . . (f (x)) . . .)).

Por exemplo, sef for a função x 7→ x+1, então a n-ésima repetição da aplicação de f é a função x 7→ x + n.

Sef for a operação de elevar um número ao quadrado, então a n-ésima repetição da aplicação def é a função que eleva o seu argumento a 2n.

Escreva um procedimento chamadorepeated, que recebe como argumentos um procedimento que calculaf e um inteiro positivo n e retorna um procedimento que calcula a n-ésima repetição da aplicação def . O seu procedimento deverá poder ser usado da seguinte forma:

((repeated square 2) 5) 625

Sugestão: Pode ser conveniente usar ocomposedo 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 de sinal. Sef é uma função e dx é um número pequeno, então a versão alisada de f é a função cujo valor no pontox é a média de f (x − dx), f(x) e f(x + dx).

Escreva um procedimentosmoothque recebe como argumento um procedimento que calculaf e retorna um procedimento que calculaf alisada.

Algumas vezes, pode ser útil alisar repetidamente uma função (isto é, alisar a função alisada e assim sucessivamente) para obter a função alisada n-vezes. Mostre como é que poderia gerar a função alisada n-vezes de qualquer função usandosmootherepeateddo 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))

(37)

8 ABSTRACÇÃO DE DADOS PARES EM SCHEME 36

8

Abstracção de dados

Pares em Scheme

Sumário Resumo

(38)

8 ABSTRACÇÃO DE DADOS PARES EM SCHEME 37

Exercícios

Exercício 8.1

Diga qual o resultado de avaliar cada uma das seguintes expressões. Se alguma delas der origem a 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"))

(39)

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.2

Represente 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:

(40)

8 ABSTRACÇÃO DE DADOS PARES EM SCHEME 39 Exercício 8.3

Considere as seguintes definições para o procedimento make-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-ratque considere argumentos positivos e negativos.make-ratdeve 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ó o numerador é 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 segmentos de recta num plano. Cada seg-mento é representado por um par de pontos: um ponto inicial e um ponto final.

Defina um construtor make-segmente os selectores start-segment e end-segment que 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 a coordenaday.

Especifique o construtormake-pointe os selectoresx-pointey-pointque definem esta representação.

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

Resposta:

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

(41)

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 os resultados 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 os procedimentos 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 coordenadas y do seu lado superior (top) e do seu lado inferior (bottom) e as coordenadas x do seu lado esquerdo (left) e do seu lado direito (right).

Os selectores vão dar precisamente cada um destes valores, independentemente da representação interna que for usada para os rectângulos.

; Numa implementacao, vamos definir os rectangulos como um par de pontos, ; o TopLeft e o BottomRight

(define (make-rect top left right bottom)

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

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

(42)

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.6

Com base nas respostas aos exercícios anteriores, escreva um procedimentodentro-rectangulo, que recebe um rectângulo e um ponto e retorna#tse o ponto estiver dentro do rectângulo (in-cluindo a fronteira) e#fse 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

(43)

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.7

Defina os seguintes procedimentos que operam sobre listas. Os seus procedimentos devem dar erro (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 procedimento primeiro-par que recebe uma lista e retorna um par com os dois primeiros elementos da lista.

2. O procedimento maior-elementoque recebe uma lista de inteiros e retorna o maior elemento dessa lista.

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

4. O procedimento aplica-op-com-passoque recebe uma lista e dois procedimentos e retorna outra lista, cujos elementos são obtidos aplicando o primeiro procedimento ao primeiro elemento da lista inicial, e das sucessivas listas que são obtidas por aplicação do segundo 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-paresque recebe uma lista de pares e imprime os pares, um por linha. O seu procedimento 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 -> 12345678 Jorge -> 23456789 Maria -> 34567890 Rui -> 45678901 Fim da lista Resposta:

(44)

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, recebeu () >(primeiro-par (list 1))

primeiro-par: espera uma lista com pelo menos 2 elementos, recebeu (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, pois isso 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 menos 1 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)

(45)

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 um procedimento 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ámosp2com(5), o que originou este erro. No entanto, no procedimento aplica-op-com-passonão podemos resolver este problema, pois não sabemos qual vai ser o procedimento passado no terceiro argumento. Assim, quando chamarmosaplica-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 usado para 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ão dar 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 um procedimento 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 ()))

(46)

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 processo iterativo neste caso, pois não sabemos acrescentar elementos no fim de listas. Para isso deveríamos definir um outro procedimento, mas ficaria muito pouco eficiente porque tinha que percorrer sempre toda 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 -> 12345678 Jorge -> 23456789 Maria -> 34567890 Rui -> 45678901 Fim da lista

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

imprime-lista-de-pares: espera uma lista de pares, recebeu ("Rui")

(47)

9 LISTAS EM SCHEME 46

9

Listas em Scheme

Sumário Resumo

(48)

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 procedimento reverse, que recebe como argumento uma lista e retorna 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 ir colocando 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 ()))

(49)

9 LISTAS EM SCHEME 48

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

Exercício 9.3

Defina um procedimentomap, que recebe como argumentos um procedimento de um argumento e uma lista, e retorna a lista dos resultados produzidos aplicando o procedimento a cada elemento da 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-listrecebe como argumento uma lista de números e 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 as definiçõ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)

(50)

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 procedimentosquare-listdo exercício anterior 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 resposta pela ordem inversa à desejada. Porquê?

O Luís tenta então corrigir este erro trocando os argumentos docons: (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 procedimento for-each é semelhante aomap. Recebe como argumentos um procedimento e uma lista de elementos. No entanto, em vez de formar uma lista com os resultados,for-eachapenas aplica o procedimento a cada um dos elementos de cada vez, da esquerda para a direita. Os valores retornados pela aplicação do procedimento aos elementos não são usados —for-eaché usado com procedimentos que executam uma acção, tal como imprimir. Por exemplo:

(51)

9 LISTAS EM SCHEME 50

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

57 321 28

O valor retornado pela chamada a for-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)) 57 321 28 #t Exercício 9.7

Implemente o procedimentoimprime-lista-de-paresda aula passada usando o proce-dimento for-each. Lembre-se que o procedimento recebe uma lista de pares e imprime os pares, 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 -> 12345678 Jorge -> 23456789 Maria -> 34567890 Rui -> 45678901 Fim 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))

(52)

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 -> 12345678 Jorge -> 23456789 Maria -> 34567890 Rui -> 45678901 #t

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

imprime-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 decars ecdrs que seleccionem o 7 de cada uma das listas 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

(53)

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))

(54)

10 LISTAS EM ÁRVORE EM SCHEME 53

10

Listas em árvore em Scheme

Sumário Resumo

(55)

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-reverseque recebe uma lista como argumento e retorna a lista com os seus elementos 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 procedimentoreverserecebe como argumento uma lista e retorna uma lista com 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 procedimento fringe que recebe como argumento uma árvore (representada como uma lista de listas) e retorna uma lista cujos elementos são todas as folhas da árvore da esquerda para a direita. Por exemplo,

(56)

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-treeanálogo aosquare-list(do Livro — 2.18). O procedimentosquare-treedeve-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)

(57)

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 anterior para produzir um procedimento tree-map, com a propriedade quesquare-treepoderia 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))

(58)

10 LISTAS EM ÁRVORE EM SCHEME 57 Exercício 10.5

(Livro — 2.32) Podemos representar um conjunto como uma lista de elementos distintos, e podemos representar o conjunto de todos os subconjuntos de um conjunto como uma lista de listas. 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ção de um procedimento que gera o conjunto dos subconjuntos de um conjunto e dê uma explicação clara 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))

(59)

11 MAIS EXERCÍCIOS SOBRE LISTAS 58

11

Mais exercícios sobre listas

Sumário Resumo

Referências

Documentos relacionados

Dessa forma, considerando os setores da agropecuária, indústria e serviços, ou cadeia produtiva como uma rede de inter-relações sob diversos e variados níveis entre os

A prova do ENADE/2011, aplicada aos estudantes da Área de Tecnologia em Redes de Computadores, com duração total de 4 horas, apresentou questões discursivas e de múltipla

4.15 - Superfície de resposta e curva de contorno para a concentração residual de sacarose em função da concentração celular no inóculo e da concentração inicial de sacarose ...69

O REITOR DA UNIVERSIDADE DO ESTADO DA BAHIA (UNEB), no uso de suas atribuições legais e regimentais, torna público o presente Edital e convoca os interessados

Todos os preços negociados, descontos praticados, pedidos de faturamento ou vendas feitas devem ser realizados sempre conforme as políticas inter- nas da Biolab, de acordo com

a) Advertência, nos casos de menor gravidade; b) Suspensão do direito de licitar e impedimento de contratar com a Administração, pelo prazo de até cinco anos, se convocada

Esse fator ainda carece de uma análise à parte, haja vista que a grande quantidade de dados para ele é também dados que constituem exemplos de genitivo (pois todo genitivo é

Equipamentos de emergência imediatamente acessíveis, com instruções de utilização. Assegurar-se que os lava- olhos e os chuveiros de segurança estejam próximos ao local de