Aulas práticas da cadeira de Introdução à Programação
|
|
|
- Caio Fraga Cortês
- 7 Há anos
- Visualizações:
Transcrição
1 Aulas práticas da cadeira de Introdução à Programação Ana Cardoso Cachopo Ano Lectivo 1998/1999
2 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 Listas em árvore em Scheme Mais exercícios sobre listas Quote Modularidade, objectos e estado 68
3 1 Apresentação Sumário Esta aula vai servir para nos conhecermos melhor... Eu Eles IP Nome Entrei para a LEIC no primeiro ano em que ele existiu Escolhi o ramo de Inteligência Artificial Dou aulas desde o 4 o ano no Grupo de Inteligência Artificial do IST. Ver 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. 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 no camoes. Na biblioteca da LEIC, custa 1000$00 e uma fotografia Página da cadeira: Grupo de news ist.cadeiras.leic.ip Endereço de correio electrónico [email protected]
4 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. Resumo
5 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 ( ) (- 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)) > > ( ) 12
6 > (- 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 ( ))) 3(6 2)(2 7) (/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5))))) (* 3 (- 6 2)
7 (- 2 7))) O que dá -37/150 Se algum dos números fosse um real, o resultado seria Exercício 2.3 Defina um procedimento que calcula o volume de uma esfera v = 4 3 πr3. (define (volume raio) (* (/ 4 3) pi (cubo raio))) (define (cubo x) (* x x x)) (define pi ) 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. (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 (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) (sum-of-squares (largest a b c) (second-largest a b c)))
9 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: Password must contain at least two alphabetic characters and
10 at least one numeric or special character. New password: Re-enter new password: Sair do sistema logout 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 mkdir nomedir rmdir nomedir cd [nomedir] ls Mostra a directoria corrente Cria uma directoria chamada nomedir Remove a directoria nomedir, se estiver vazia Muda para a directoria nomedir Lista os ficheiros da directoria corrente Manipular ficheiros cp nomefichvelho nomefichnovo Copia nomefichvelho para nomefichnovo cp nomefich* nomedir Copia um conjunto de ficheiros para a directoria nomedir mv nomefichvelho nomefichnovo Muda o nome de nomefichvelho para nomefichnovo mv nomefich* nomedir Move um conjunto de ficheiros para nomedir 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 primeiras n linhas de um conjunto de ficheiros tail -n nomefich* Mostra as últimas n linhas de um conjunto de ficheiros Imprimir ficheiros
11 lpr [-P impressora] nomefich* Imprime os ficheiros na impressora lpq [-P impressora] job* userid* Escreve o status dos jobs especificados e/ou dos jobs dos utilizadores especificados que estão na impressora lprm [-P impressora] job* userid* Cancela todos os jobs especificados e/ou os jobs dos utilizadores especificados que estão na impressora 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, onde mudanca é 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 o more) as páginas do manual associadas a palavra man -k palavra Mostra as entradas do manual que contêm palavra Exemplos: man -k mode, man chmod Utilização do Mail mailx endereco Envia uma mensagem para endereco a partir da shell do UNIX. ctrl-d significa endof-file mailx [-f nomefich] [endereco]* Envia o ficheiro nomefich para endereco 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 ctrl-z Suspend - suspende o processo que está a ser executado
12 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 resultado de um processo num ficheiro Internet ist.cadeiras.leic.ip News grupos de discussão de assuntos de interesse para a cadeira, exercicios, avisos importantes, etc (emacs,tin, pine) WWW página da cadeira de IP (lynx, netscape, internet explorer) Manipular processos ps kill numprocesso bg [numprocesso] fg [numprocesso] & Mostra os processos do utilizador Mata processos do utilizador Passa um processo do utilizador para background Passa um processo do utilizador para foreground Executa um processo do utilizador em background No camoes setenv DISPLAY xxx:0 Onde xxx é 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 sistema O emacs O emacs é um editor de texto. Tem extensões para escrever código em várias linguagens de programação, ler mail e news, entre outras. O emacs tem ajuda e documentação disponível no menu Help, que pode ser utilizada para aprender a trabalhar com ele.
13 Exercícios Exercício 3.1 Escreva em Scheme os seguintes procedimentos: Um procedimento chamado hipotenusa que, dados os comprimentos dos dois catetos de um triângulo rectângulo, calcula o comprimento da hipotenusa. Dados os comprimentos dos catetos a e b do triângulo, a hipotenusa h é calculada como: h = a 2 + b 2 Um procedimento chamado perimetro que, 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, é imprescindí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 endereç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.
14 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 Exercícios Exercício 4.1 Defina um procedimento que calcula uma potência inteira de x. Note que x n = x x n 1 e x 0 = 1. (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 procedimento soma, que recebe dois inteiros superiores ou iguais a zero x e y, e calcula a soma entre eles. 2. O procedimento igual?, que dados dois inteiros superiores ou iguais a zero x e y, retorna verdadeiro se eles forem iguais e falso caso contrário. 3. O procedimento menor?, que dados dois inteiros superiores ou iguais a zero x e y, indica se x é menor que y. 4. O procedimento produto, que calcula o produto entre dois inteiros superiores ou iguais a zero x e y. Para definir este procedimento pode também usar o procedimento soma. 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)))
16 Exercício 4.3 O número de combinações de m objectos n a n pode ser calculado pela seguinte função: 1 se n = 0, Comb(m, n) = 1 se n = 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 e m > 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? (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á ser Para saber quanto dinheiro se tem que gastar, basta multiplicar este valor por 40$00, que é quanto custa cada aposta; (* ), o que dá Isto significa que, para ter a certeza de ganhar o primeiro premio, teria que gastar mais de contos!!! Exercício 4.4 (Livro 1.4) Repare que o nosso modelo de avaliação permite a existência de combinações cujos 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)) Este procedimento soma a com o modulo de b, pois o operador utilizado é + ou -, conforme b 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 se deparou usa avaliação pela ordem aplicativa ou avaliação pela ordem normal. Ele define os dois procedimentos:
17 (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 avaliaçã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 especial if é 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.) 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 avaliar as sub-expressões test, 0 e (p) e só depois é que se aplica o operador (resultante da avaliação de test). Por isso, e uma vez que p corresponde 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 especial if aos seus argumentos. Neste caso, como a condição do if (= 0 0) tem o valor verdadeiro, é a primeira alternativa que é avaliada e é retornado o valor 0. Exercício 4.6 (Livro 1.6) A Alice não percebe porque é que o if precisa de ser uma forma especial. Porque é que não o posso definir como um procedimento normal em termos do cond? pergunta ela. Eva, uma amiga sua, diz que isso é possível e define uma nova versão do if: (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 o new-if para re-escrever o programa da raíz quadrada: (define (improve guess x) (average guess (/ x guess)))
18 (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. 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 teste good-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 se y é uma aproximação para a raíz cúbica de x, então uma melhor aproximação é dada por x y 2 +2y 3 Use esta fórmula para implementar um procedimento que calcula raízes cúbicas análogo ao que calcula raízes quadradas. (define (improve-cube guess x) (/ (+ (/ x (square guess)) (* 2 guess)) 3)) (define (cube x) (* x x x))
19 (define (cubert-good-enough? guess x) (< (abs (- (cube guess) x)) )) (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 de sen(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. (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 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 Exercícios Exercício 5.1 O número de combinações de m objectos n a n pode ser calculado pela seguinte função: 1 se n = 0, Comb(m, n) = 1 se n = m, Comb(m 1, n) + Comb(m 1, n 1) se m > n, m > 0 e n > 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 e m 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? (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á ser Para saber quanto dinheiro se tem que gastar, basta multiplicar este valor por 40$00, que é quanto custa cada aposta; (* ), o que dá Isto significa que, para ter a certeza de ganhar o primeiro premio, teria que gastar mais de 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 procedimentos inc, que incrementa o seu argumento de uma unidade, e dec, 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 Exercício 5.3 Defina um procedimento que calcula uma potência inteira de x usando um processo iterativo. Note que x n = x x n 1 e x 0 = 1. Modifique o procedimento anterior para que passe também a conseguir calcular potências em que o expoente é negativo. Note que x n = 1. x n 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 procedimento produto, que calcula o produto entre dois inteiros superiores ou iguais a zero x e y. 1. Usando um processo recursivo 2. Usando um processo iterativo Usando um processo recursivo, fica: (define (produto x y) (if (zero? y) 0 (+ x (produto x (sub1 y)))))
23 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 Sumário Resumo
25 Exercícios Exercício 6.1 (Livro 1.15) O seno de um ângulo (especificado em radianos) pode ser calculado usando a aproximação sin x x se x for suficientemente pequeno, e a identidade trigonométrica sin x = 3 sin x 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 procedimento p é 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 procedimento sine quando avaliamos (sine a)? 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 o let, o procedimento sine 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 (/ ))) (p (p (sine (/ )))) (p (p (p (sine (/ ))))) (p (p (p (p (sine (/ )))))) (p (p (p (p (p (sine (/ )))))) (p (p (p (p (p 0.05 ))))) Isto corresponde a 5 chamadas ao procedimento p.
26 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. a Ou seja, estamos interessados em resolver a seguinte inequação em ordem a n: 3 0,1. n Fazendo esse desenvolvimento, ficamos com a 0,1 3 n 10a 3 n Log 3 10a n Isto significa que este procedimento tem ordem de crescimento em tempo e em espaço de Log 3 10a. 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ção f entre a e b pode ser aproximado por h 3 [y 0 + 4y 1 + 2y 2 + 4y 3 + 2y y n 2 + 4y n 1 + y n ] onde h = (b a)/n, para algum inteiro par n, e y k = f(a + kh). (Aumentar o n aumenta a precisão da aproximação.) Defina um procedimento que recebe como argumentos f, a, b e n e retorna o valor do integral, calculado usando a Regra de Simpson. Use o seu procedimento para integrar o procedimento cubo entre 0 e 1 (com n = 100 e n = 1000), e compare os resultados com os do procedimento integral apresentado na página 60 do livro. Nota: Deve usar o procedimento sum, 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)))) Exercício 6.3 (Livro 1.30) O procedimento sum apresentado 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 (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 semelhantes, que podem ser capturadas como procedimentos de ordem superior. Escreva um procedimento análogo chamado product, que retorna o produto dos valores de uma função para pontos pertencentes a um intervalo. Mostre como definir o factorial em termos do product. Use também o product para calcular aproximações de π usando a fórmula π 4 = Se o seu procedimento product gerar um processo recursivo, escreva um que gere um processo iterativo. Se gerar um processo iterativo, escreva um que gere um processo recursivo. 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 = Podemos usar o product para calcular o valor de cada uma destas fracções. Depois, basta multiplicar 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. Mas também podemos considerar que a série, desde o termo 1 até ao termo n vai progredindo da
28 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 e product sã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) Accumulate recebe como argumentos o mesmo term e as mesmas especificações do intervalo a e b, bem como um procedimento combiner (de 2 argumentos) que especifica como é que o termo corrente deve ser combinado com a acumulação dos termos precedentes e um null-value, que especifica qual o valor a usar quando os termos acabam. Escreva o procedimento accumulate e mostre como é que sum e product podem ser definidos como simples chamadas a accumulate. 2. Se o seu procedimento accumulate gerar um processo recursivo, escreva um que gere um processo iterativo. Se gerar um processo iterativo, escreva um que gere um processo recursivo. 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 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. Ao avaliar (f f), temos a seguinte sequência de avaliações: (f f) (f 2) (2 2) Como 2 não é o nome de nenhum procedimento, ao avaliar a última expressão vamos obter um erro, pois não é possível aplicar o procedimento 2 a nenhuns argumentos. Exercício Escreva um procedimento que faz a composição de procedimentos. Por exemplo, a chamada (compoe f g x) aplica o procedimento f ao resultado de aplicar o procedimento g a x. 2. Com base no procedimento compoe, escreva um procedimento triplo-fact, que calcula o triplo do factorial do seu argumento. Por exemplo, (triplo-fact 3) deverá dar (define (compoe f g x) (f (g x)))
30 2. (define (triplo-fact x) (compoe (lambda (x) (* x 3)) fact x)) Exercício 6.8 Com base no procedimento sum, escreva um procedimento para calcular o valor de sen(x) utilizando a expansão em série: sen(x) = x 1! x3 3! + x5 5! x7 7! +... Assuma que já existem os procedimentos fact e pot que calculam o factorial e a potência, respectivamente. O seu procedimento deve receber, para além de x, o número n de termos que devem ser considerados. (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 procedimento seno-com-sum seria 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 o sum recebe 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-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)))
31 Exercício 6.9 Suponha que tem definido o procedimento comb, que recebe dois inteiros maiores ou iguais a zero, m e n, e calcula o número de combinações de m elementos n a n. 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. (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)
32 7 Métodos gerais: procedimentos que retornam procedimentos Sumário Resumo
33 Exercícios Exercício 7.1 Considere definido o procedimento sum: (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) 1. Soma os números entre 4 e Soma as raízes quadradas dos múltiplos de 5 entre 5 e Para cada um dos números entre 1 e 5, soma os números entre 1 e esse número: (1+(1+2)+( ) + ( ) + ( )) Exercício 7.2 Considere a seguinte expressão matemática: 3x! + 4(x!) 3 1. Escreva um procedimento calc-expr que calcule o seu valor. 2. Usando a estrutura de blocos, garanta que o seu procedimento recebe sempre um argumento 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 especial let. (c) Neste caso, não devo definir o procedimento cubo. (d) O procedimento cubo, se for definido, deve ser definido dentro do procedimento calc-expr. 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)))))
34 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 argumento é válido só seria feito uma vez, mesmo que fosse feito no procedimento 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 especial let, 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 procedimento cubo faz é 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 procedimento cubo pode ser útil noutros procedimentos. Por isso, deve ser definido fora do procedimento calc-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, se add1 for 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ê? (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) ((lambda (x) (add1 (add1 x))) 5)
35 (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 (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 f(g(x)). Defina um procedimento compose que implementa a composição. Por exemplo, se inc for um procedimento que adiciona 1 ao seu argumento, ((compose square inc) 6) Compare o procedimento compose com o procedimento compoe da aula passada. Porque é que eles são diferentes? 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 argumentos desses procedimentos. Retornava o resultado da aplicação dos procedimentos ao valor recebido. O procedimento compose recebe apenas os procedimentos e retorna outro procedimento. O resultado do procedimento compose pode ser usado como primeiro elemento de uma expressão em Scheme e o resultado do procedimento compoe não.
36 Exercício 7.5 (Livro 1.43) Se f for uma função numérica e n um inteiro positivo, então podemos formar 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, se f for a função x x+1, então a n-ésima repetição da aplicação de f é a função x x + n. Se f for a operação de elevar um número ao quadrado, então a n-ésima repetição da aplicação de f é a função que eleva o seu argumento a 2 n. Escreva um procedimento chamado repeated, que recebe como argumentos um procedimento que calcula f e um inteiro positivo n e retorna um procedimento que calcula a n-ésima repetição da aplicação de f. O seu procedimento deverá poder ser usado da seguinte forma: ((repeated square 2) 5) 625 Sugestão: Pode ser conveniente usar o compose do execício anterior. (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. Se f é uma função e dx é um número pequeno, então a versão alisada de f é a função cujo valor no ponto x é a média de f(x dx), f(x) e f(x + dx). Escreva um procedimento smooth que recebe como argumento um procedimento que calcula f e retorna um procedimento que calcula f 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 usando smooth e repeated do exercício anterior. (define (smooth f) (let ((dx )) (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 Sumário Resumo
38 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)) >(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"
39 >(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))))
40 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 denominador aos números mais pequenos possível. (Livro 2.1) Defina uma versão melhor de make-rat que considere argumentos positivos e negativos. 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ó o numerador é que é negativo. (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 segmento é representado por um par de pontos: um ponto inicial e um ponto final. Defina um construtor make-segment e 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 coordenada x e a coordenada y. Especifique o construtor make-point e os selectores x-point e y-point que definem esta representação. Usando os seus selectores e construtores, defina um procedimento midpoint-segment que recebe um segmento de recta como argumento e retorna o seu ponto médio (o ponto cujas coordenadas são a média das coordenadas dos pontos que definem o segmento). (define (make-segment ip fp) (cons ip fp))
41 (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? Antes de mais nada, devemos definir a interface dos procedimentos que vão manipular rectângulos. 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 (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 procedimento dentro-rectangulo, que recebe um rectângulo e um ponto e retorna #t se o ponto estiver dentro do rectângulo (incluindo a fronteira) e #f se estiver fora do rectângulo. (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 )) #t
43 >(dentro-rectangulo (make-point 10 10) (make-rect )) #f >(dentro-rectangulo (make-point 1 5) (make-rect )) #t Exercício 8.7 Defina os seguintes procedimentos que operam sobre listas. Os seus procedimentos devem dar erro (usando o error) quando isso se justificar. Quando for possível, escreva dois procedimentos, 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-elemento que recebe uma lista de inteiros e retorna o maior elemento dessa lista. 3. O procedimento soma-elementos que recebe uma lista e retorna a soma de todos os elementos dessa lista. 4. O procedimento aplica-op-com-passo que 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 ) (lambda (x) (* 2 x)) cddr) deverá retornar (2 6 10). 5. O procedimento imprime-lista-de-pares que 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" ) (cons "Jorge" ) (cons "Maria" ) (cons "Rui" ))) Deverá imprimir Luisa -> Jorge -> Maria -> Rui -> Fim da lista
44 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) >(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 )) (define (soma-elementos l) (if (null? l) 0 (+ (car l)
45 (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 )) (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 ) (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ámos p2 com (5), o que originou este erro. No entanto, no procedimento aplica-op-com-passo não podemos resolver este problema, pois não sabemos qual vai ser o procedimento passado no terceiro argumento. Assim, quando chamarmos aplica-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 ()) (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 ) (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 Exemplos: (aplica-op-com-passo (list ()) (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" ) (cons "Jorge" ) (cons "Maria" ) (cons "Rui" ))) Luisa -> Jorge -> Maria -> Rui -> Fim da lista >(imprime-lista-de-pares (list (cons "Luisa" ) (cons "Jorge" ) (cons "Maria" ) "Rui")) Luisa -> Jorge -> Maria -> imprime-lista-de-pares: espera uma lista de pares, recebeu ("Rui") Este exemplo gera um processo iterativo e neste caso não faz sentido criar um recursivo.
47 9 Listas em Scheme Sumário Resumo
48 Exercícios Exercício 9.1 (Livro 2.17) Defina um procedimento last-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 )) (34) >(last-pair ()) cdr: expects argument of type <pair>; given () >(last-pair (list ())) (()) 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 )) ( ) (define (reverse l) (if (null? l) () (cons (car l) (reverse (cdr l))))) Exemplos: >(reverse (list )) ( ) 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 ())) Exemplos:
49 >(reverse (list )) ( ) Exercício 9.3 Defina um procedimento map, 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 )) ( ) (define (map proc l) (if (null? l) () (cons (proc (car l)) (map proc (cdr l))))) Exemplos: >(map abs (list )) ( ) >(map (lambda (x) (* x 5)) (list )) ( ) Exercício 9.4 (Livro 2.21) O procedimento square-list recebe como argumento uma lista de números e retorna uma lista com os quadrados desses números. (square-list (list )) ( ) Seguem-se duas definições diferentes para o procedimento square-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 <??> <??>)) (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))
50 Exemplos: >(square-list (list )) ( ) Exercício 9.5 (Livro 2.22) O Luís tenta re-escrever o primeiro procedimento square-list do 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 procedimento square-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 do 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ê. Exemplos: Exercício 9.6 (Livro 2.23) O procedimento for-each é semelhante ao map. Recebe como argumentos um procedimento e uma lista de elementos. No entanto, em vez de formar uma lista com os resultados, for-each apenas 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 (for-each (lambda (x) (newline) (display x)) (list )) O valor retornado pela chamada a for-each (não ilustrado acima) pode ser qualquer coisa, como verdadeiro. Apresente uma implementação para o procedimento for-each. (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 )) #t Exercício 9.7 Implemente o procedimento imprime-lista-de-pares da aula passada usando o procedimento 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" ) (cons "Jorge" ) (cons "Maria" ) (cons "Rui" ))) Deverá imprimir Luisa -> Jorge -> Maria -> Rui -> Fim da lista (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 Nesta definição, o fim da lista é assinalado pelo valor retornado pelo procedimento for-each. Exemplos: >(imprime-lista-de-pares (list (cons "Luisa" ) (cons "Jorge" ) (cons "Maria" ) (cons "Rui" ))) Luisa -> Jorge -> Maria -> Rui -> #t >(imprime-lista-de-pares (list (cons "Luisa" ) (cons "Jorge" ) (cons "Maria" ) "Rui")) Luisa -> Jorge -> Maria -> 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. >(list 1 (list 2 (list 3 4))) (1 (2 (3 4))) Exercício 9.9 (Livro 2.25) Apresente combinações de cars e cdrs que seleccionem o 7 de cada uma das listas seguintes: (1 3 (5 7) 9) ((7)) (1 (2 (3 (4 (5 (6 7)))))) >(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 definimos x e y como sendo duas listas:
53 (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 expressões? (append x y) (cons x y) (list x y) >(append x y) ( ) >(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 Sumário Resumo
55 Exercícios Exercício 10.1 (Livro 2.27) Modifique o procedimento reverse (do Livro 2.18) para produzir um procedimento deep-reverse que 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 procedimento reverse recebe 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 ())) (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 (define x (list (list 1 2) (list 3 4))) (fringe x) ( ) (fringe (list x x)) ( ) (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) ( ) >(fringe (list x x)) ( ) >(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 procedimento square-tree análogo ao square-list (do Livro 2.18). O procedimento square-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 procedimento map. (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))
57 Exemplos: >(square-tree (list 1 (list 2 (list 3 4) 5) (list 6 7))) (1 (4 (9 16) 25) (36 49)) Usando o procedimento map, 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 que square-tree poderia ser definido como: (define (square-tree tree) (tree-map square tree)) (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 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))))) (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))
59 11 Mais exercícios sobre listas Sumário Resumo
60 Exercícios Exercício 11.1 Considere 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 árvores binárias: 1. percorre-inorder recebe uma árvore binária e retorna uma lista com todas as sua folhas, 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 sua folhas, 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 sua folhas, percorrendo primeiro a árvore esquerda, depois a árvore direita e depois a raiz da árvore inicial. Exercício 11.2 Uma á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ão maiores 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 insere na árvore. 2. ordena-lista que recebe uma lista de elementos e retorna uma nova lista com os elementos ordenados. Exercício 11.3 Escreva um procedimento filtra que recebe um predicado e uma lista e retorna uma lista que contém apenas os elementos da lista inicial que satisfazem o predicado. Por exemplo:
61 (filtra even? (list )) (2 4) (filtra even? (list )) () (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.4 Escreva um procedimento todos? que recebe um predicado e uma lista e retorna verdadeiro se todos os elementos da lista satisfizerem o predicado e falso caso contrário. Por exemplo: (todos? even? (list )) #f (todos? even? (list 2 4 6)) #t (define (todos? pred lst) (cond ((null? lst) #t) ((pred (first lst)) (todos? pred (rest lst))) (else #f))) Exercício 11.5 Escreva um procedimento algum? que recebe um predicado e uma lista e retorna verdadeiro se algum dos elementos da lista satisfizer o predicado e falso caso contrário. Por exemplo: (algum? odd? (list )) #t (algum? odd? (list 2 4 6)) #f (define (algum? pred lst) (cond ((null? lst) #f) ((pred (first lst)) #t) (else (algum? pred (rest lst)))))
62 Exercício 11.6 Escreva um procedimento substitui que recebe dois elementos e uma lista e retorna uma outra lista que resulta de substituir todas as ocorrências do primeiro elemento pelo segundo na lista inicial. Por exemplo: (substitui 2 3 (list )) ( ) (substitui 2 3 (list )) ( ) (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.7 Escreva um procedimento fold-right que recebe um procedimento de dois argumentos, o valor inicial de um acumulador e uma lista e retorna o resultado de aplicar o procedimento ao elemento inicial e ao resultado de aplicar o procedimento a todos os elementos que estão à sua direita. Quando a lista for vazia, este procedimento deve retornar o valor inicial. Por exemplo: (fold-right + 0 (list )) 10 (fold-right + 0 ()) 0 (define (fold-right proc inicial lst) (if (null? lst) inicial (proc (first lst) (fold-right proc inicial (rest lst))))) Exercício 11.8 Com base no procedimento fold-right escreva os seguintes procedimentos: 1. multiplica-lista que recebe uma lista e retorna o produto de todos os seus elementos. 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 da lista inicial pela ordem inversa.
63 4. junta-listas que recebe duas listas e retorna outra lista que resulta de juntar as duas. 1. (define (multiplica-lista lst) (if (null? lst) (error "multiplica-lista: espera uma lista com pelo menos 1 elemento, recebeu" lst) (fold-right * 1 lst))) (multiplica-lista (list )) 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 elemento, recebeu" lst) (fold-right max (first lst) (rest lst)))) (maximo-lista (list )) 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 )) ( ) (inverte-lista ()) () 4. (define (junta-listas lst1 lst2) (fold-right cons lst2 lst1)) (junta-listas (list ) (list 5 6 7)) ( ) (junta-listas () (list 5 6 7)) (5 6 7) Exercício 11.9 Uma forma de compactar listas de números é, dada uma lista de números (possivelmente repetidos), transformá-la numa lista em que ocorrências consecutivas de um mesmo número são substituídas por um par, em que o primeiro elemento é o número de vezes que o número aparece repetido e o segundo elemento é o número. Escreva o procedimento run-length-encode que compacta listas de inteiros. Por exemplo,
64 (run-length-encode ( )) ((7. 1) 2 (4. 3) (4. 4) 1 (4. 3)) (run-length-encode ( )) ( (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. Escreva o procedimento run-length-decode que, dada uma lista de inteiros compactada, retorna a lista original. Por exemplo, (run-length-decode ((7. 1) 2 (4. 3) (4. 4) 1 (4. 3))) ( ) (run-length-decode ( (4. 3) (4. 4) (2. 1) (5. 3))) ( ) (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)))))
65 12 Quote Sumário Resumo
66 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)) (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 procedimento memq, que recebe um símbolo e uma lista e retorna falso se o símbolo não estiver contido na lista (isto é, não for eq? a nenhum dos elementos da lista) e a sublista que começa com a primeira ocorrência do símbolo na lista caso contrário. Por exemplo, (memq apple (pear banana prune)) #f (memq apple (x (apple sauce) y apple pear)) (apple pear) (define (memq item lst) (cond ((null? lst) #f) ((eq? item (first lst)) lst) (else (memq item (rest lst)))))
67 Exercício 12.3 (Livro 2.53) O que é que o interpretador de Scheme imprime como resposta à avaliação de cada 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)) (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ão equal? se contiverem elementos iguais e estes estiverem pela mesma 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 definir equal? recursivamente em termos da igualdade básica entre símbolos eq?, dizendo que a e b são equal? se forem ambos símbolos e forem eq? ou forem ambos listas em que (first a) é equal? a (first b) e (rest a) é equal? a (rest b). Usando esta ideia, implemente equal? como um procedimento.
68 (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ê. 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 uma lista 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 o procedimento first à lista (quote abracadabra) tem como resultado o primeiro elemento da lista, que é o símbolo quote.
69 13 Modularidade, objectos e estado Sumário Resumo
70 Exercícios Exercício 13.1 Diga o que é impresso pelo interpretador de Scheme ao avaliar cada uma das seguintes expressões: (define a 3) (set! a "ola") (+ a 1) (begin (let ((a 5)) (+ a (* )) (sqrt (length (1 a b "bom dia" (2 5) 3)))) (display a) a) (set! c 78) >(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 (* )) (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 um argumento numérico e acumula os seus argumentos numa soma. De cada vez que é chamado, retorna a soma acumulada até ao momento. Escreva um procedimento make-accumulator que gera acumuladores, cada um dos quais mantendo uma soma independente. O valor de entrada para o procedimento make-accumulator deve especificar o valor inicial da soma. Por exemplo,
71 (define A (make-accumulator 5)) (A 10) 15 (A 10) 25 (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 vezes que um procedimento é chamado durante o decurso de uma computação. Escreva um procedimento make-monitored que recebe um procedimento f como argumento, que por sua vez é um procedimento de um argumento. O resultado retornado pelo procedimento make-monitored é um terceiro procedimento mf que mantém um registo do número de vezes que foi chamado através de um contador interno. Se o valor de entrada para mf for o símbolo how-many-calls?, então mf deve retornar o valor do contador. Se o valor de entrada for o símbolo reset-count, então mf deve inicializar o contador a zero. Para qualquer outro valor de entrada, mf retorna o valor de aplicar f a esse valor e incrementa o contador. Por exemplo, podemos criar uma versão monitorizada do procedimento sqrt: (define s (make-monitored sqrt)) (s 100) 10 (s how-many-calls?) 1 (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.4 Desenhe o diagrama dos ambientes criados pelos seguintes exemplos de código:
72 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 é (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 representações para tipos abstractos de dados. Por exemplo, podemos criar rectângulos da seguinte 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) Exercício 13.5 Introduzir a forma especial set! na nossa linguagem obriga-nos a pensar no significado de igualdade e mudança. Dê exemplos de procedimentos simples que sejam: 1. Um procedimento referencialmente transparente
73 2. Um procedimento referencialmente opaco (não transparente) 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 que st1 e st2 são iguais, pois um pode ser substituido pelo outro em qualquer lugar da computação sem alterar o resultado. Uma linguagem que suporta o conceito de que iguais podem ser substituidos por iguais numa expressão sem alterar o valor da expressão diz-se referencialmente transparente. 2. A transparência referencial é violada quando introduzimos set! na linguagem, o que dificulta a verificação de quando é que podemos simplificar expressões substituindo-as por outras equivalentes. (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
Exercícios da cadeira de Introdução à Programação. Ana Cardoso Cachopo João Cachopo António Leitão
Exercícios da cadeira de Introdução à Programação Ana Cardoso Cachopo João Cachopo António Leitão Ano Lectivo 2000/2001 1 Prefácio Este documento reúne os exercícios propostos nas aulas práticas da cadeira
UNIVERSIDADE TÉCNICA DE LISBOA INSTITUTO SUPERIOR TÉCNICO
UNIVERSIDADE TÉCNICA DE LISBOA INSTITUTO SUPERIOR TÉCNICO Resumos e Soluções para os Exercícios para as Aulas Práticas da Disciplina de Fundamentos da Programação Ana Cardoso Cachopo Ano Lectivo 2006/2007
Fundamentos de Programação
Fundamentos de Programação Soluções do primeiro teste 13 de Novembro de 2004 9:00-10:30 Nota Número: 20 Nome: Turma: Escreva o seu número em todas as folhas do teste. O espaço das respostas deve ser limitado
Fundamentos de Programação
Fundamentos de Programação Primeiro Teste 16 de Abril de 2011 09:00 10:30 Nome: Número: Esta prova, individual e sem consulta, tem 7 páginas com 9 perguntas. A cotação de cada pergunta está assinalada
Exercícios para Fundamentos da Programação Utilizando Múltiplos Paradigmas
Exercícios para Fundamentos da Programação Utilizando Múltiplos Paradigmas Pedro Adão, Fausto Almeida, Ana Cardoso-Cachopo, Pedro Amaro de Matos (editores) Departamento de Engenharia Informática Instituto
Exercícios da cadeira de Introdução à Programação
Exercícios da cadeira de Introdução à Programação Cláudia Antunes Ana Cardoso Cachopo João Cachopo Francisco Couto António Leitão Inês Lynce César Pimentel H. Sofia Pinto Ano Lectivo 2002/2003 Parte II
Fundamentos de Programação
Fundamentos de Programação Solução do Segundo Teste 23 de Janeiro de 2012 09:00 10:30 Nome: Número: 1. (1.0) Explique em que consiste a abstracção de dados, usando os termos barreiras de abstracção, encapsulação
Estruturação de Procedimentos
Capítulo 4 Estruturação de Procedimentos 4. Exercícios de revisão. Diga o que entende por linguagem estruturada em blocos. Descreva a regra associada a esta estrutura, e diga qual a sua importância. 2.
Listagens de ficheiros e directorias
Listagens de ficheiros e directorias Listagens de ficheiros e directorias Para além do tipo dos ficheiros, o modo possui nove caracteres que representam as permissões (ou protecções) associadas aos ficheiros
Fundamentos de Programação
Fundamentos de Programação Primeiro Teste 6 de Novembro de 200 09:00 0:30 SOLUÇÃO. (.0) Escolha a única afirmação incorrecta. Uma resposta certa vale valor e uma resposta errada desconta 0.4 valores. A.
2. Diga qual é a diferença entre tipos de informação elementares e tipos de informação estruturados.
Capítulo 5 Abstracção de dados 5. Exercícios de revisão. Diga o que é um tipo abstracto de informação.. Diga qual é a diferença entre tipos de informação elementares e tipos de informação estruturados.
Programação imperativa
Capítulo 8 Programação imperativa 8.1 Exercícios de revisão 1. Distinga entre programação imperativa e programação funcional. 2. Explique a necessidade da introdução do operador de atribuição. 3. Diga
Linguagem Haskell. Universidade Estadual Santa Cruz Conceitos de Linguagens de Programação. Tiago Carneiro 19 Agosto 2013
Linguagem Haskell Universidade Estadual Santa Cruz Conceitos de Linguagens de Programação Tiago Carneiro 19 Agosto 2013 1 1 Linguagem Haskell Linguagem de programação funcional É um paradigma de programação
Correção do 1º Exame de INTRODUÇÃO À PROGRAMAÇÃO Licenciatura em Engenharia Mecânica 30 de Junho de 2006, 2º Semestre
Correção do º Exame de INTRODUÇÃO À PROGRAMAÇÃO Licenciatura em Engenharia Mecânica 3 de Junho de 26, 2º Semestre. (2.) Perguntas de resposta rápida de Fortran (.4 valores cada).. Todos os componentes
Inteligência Artificial
Instituto Politécnico de Setúbal Escola Superior de Tecnologia de Setúbal Departamento de Sistemas e Informática Guia de Exercícios das Aulas Práticas Inteligência Artificial Prof Joaquim Filipe Eng. Adelaide
PROGRAMAÇÃO EM SCHEME:
Exercícios para PROGRAMAÇÃO EM SCHEME: Introdução à Programação Utilizando Múltiplos Paradigmas Departamento de Engenharia Informática Instituto Superior Técnico Universidade Técnica de Lisboa 2 Conteúdo
Aula prática 5. Funções Recursivas
Programação Funcional UFOP DECOM 2014.1 Aula prática 5 Funções Recursivas Resumo Definições recursivas são comuns na programação funcional. Nesta aula vamos aprender a definir funções recursivas. Sumário
Universidade Federal de Ouro Preto - UFOP Departamento de Computação - DECOM Programação de Computadores I - BCC701
Universidade Federal de Ouro Preto - UFOP Departamento de Computação - DECOM Programação de Computadores I - BCC701 www.decom.ufop.br/red 2017-1 Aula Teórica 05 Laços 1 Conteúdos da Aula Instrução de Repetição
ESTRUTURAS DE REPETIÇÃO - PARTE 1
AULA 15 ESTRUTURAS DE REPETIÇÃO - PARTE 1 15.1 O comando enquanto-faca- Considere o problema de escrever um algoritmo para ler um número inteiro positivo, n, e escrever todos os números inteiros de 1 a
Informática para Ciências e Engenharias 2013/14. Teórica 7
Informática para Ciências e Engenharias 2013/14 Teórica 7 Na aula de hoje... Controlo de execução ciclos condicionais while end Exemplos raiz quadrada histograma fórmula química while while e matrizes
Layout. Módulos. Normalmente, cada módulo está armazenado num ficheiro com o mesmo nome do módulo. Exemplo.hs
Layout Ao contrário de quase todas as linguagens de programação, o Haskell não necessita de marcas para delimitar as diversas declarações que constituem um programa. Em Haskell a identação do texto (isto
3. Linguagem de Programação C
Introdução à Computação I IBM1006 3. Linguagem de Programação C Prof. Renato Tinós Departamento de Computação e Matemática (FFCLRP/USP) 1 3.3. Conceitos Básicos de C: Expressões, Operadores e Bibliotecas
Seleção Múltipla Laços (while, do-while, for) AULA 05
Introdução a Programação IF669 http://www.cin.ufpe.br/~if669 Seleção Múltipla Laços (while, do-while, for) AULA 05 Ricardo Massa F. Lima [email protected] Sérgio C. B. Soares [email protected] Até aqui...
Programação Estruturada
Programação Estruturada Recursão Professores Emílio Francesquini e Carla Negri Lintzmayer 2018.Q3 Centro de Matemática, Computação e Cognição Universidade Federal do ABC Recursão Recursão 1 Recursão 2
Laços de repetição for, while, do-while
Computação Eletrônica Laços de repetição for, while, do-while Prof: Luciano Barbosa Estruturas de Repetição Imagine um programa que calcula a média de um aluno. Este programa é bastante simples, bastaria:
Conceitos de Linguagem de Programação - 2
Conceitos de Linguagem de Programação - 2 Arthur Jovita Guerra Thalles Santos Silva Universidade Estadual de Santa Cruz - Ilhéus, BA 1 de novembro de 2011 1 Revisão Natureza das linguagens de Programação
Exercícios da cadeira de Inteligência Artificial. Helena Sofia Pinto João Cachopo Daniel Gonçalves Carlos Lopes António Inês Lynce Pedro Matos
Exercícios da cadeira de Inteligência Artificial Helena Sofia Pinto João Cachopo Daniel Gonçalves Carlos Lopes António Inês Lynce Pedro Matos Ano Lectivo 2001/2002 1 Prefácio Este documento reúne os exercícios
Programação de Computadores III
Programação de Computadores III Introdução ao FORTRAN Professor Leandro Augusto Frata Fernandes [email protected] Material disponível em http://www.ic.uff.br/~laffernandes/teaching/2013.1/tcc-00.157
Laboratório de Programação II
Laboratório de Programação II Aula 02 Prof. Diemesleno Souza Carvalho [email protected] http://www.diemesleno.com.br Na aula passada vimos... Na aula passada vimos... 01 Introdução à linguagem C;
Fundamentos da Programação
Fundamentos da Programação Segundo Teste 18 de Junho de 2014 15:00 16:30 1. (1.0) Diga quais as fases por que passa o desenvolvimento de um programa no modelo estudado e o que se faz em cada uma delas.
USANDO UM MÉTODO INDUTIVO PARA RESOLVER PROBLEMAS. Bruno Maffeo Departamento de Informática PUC-Rio
USANDO UM MÉTODO INDUTIVO PARA RESOLVER PROBLEMAS Bruno Maffeo Departamento de Informática PUC-Rio MÉTODO INDUTIVO O método indutivo para resolver problemas aqui empregado inspira-se na formulação mais
1º Exame de INTRODUÇÃO À PROGRAMAÇÃO Licenciatura em Engenharia Mecânica 30 de Junho de º Semestre
º Exame de INTRODUÇÃO À PROGRAMAÇÃO Licenciatura em Engenharia Mecânica de Junho de 6 º Semestre Exame sem consulta : 6: h Nome: Número: Escreva o seu número e nome em todas as folhas de exame. O exame
LISP - Introdução. Existem vários dialectos de LISP: COMMON LISP (o mais sofisticado e mais utilizado) Outros: MAC LISP, INTERLISP, XLISP
LISP - Introdução Linguagem de alto nível, criada por John McCarty em 1959, tendo em vista facilitar a programação de sistemas de raciocínio baseados em lógica Foi adoptada como linguagem principal em
Universidade Federal de Uberlândia - UFU Faculdade de Computação - FACOM Lista de exercícios de programação em linguagem Python
Universidade Federal de Uberlândia - UFU Faculdade de Computação - FACOM Lista de exercícios de programação em linguagem Python Exercícios: Funções 1. Crie uma função que recebe como parâmetro um número
Pedro Vasconcelos DCC/FCUP. Programação Funcional 8 a Aula Listas infinitas
Programação Funcional 8 a Aula Listas infinitas Pedro Vasconcelos DCC/FCUP 2014 Listas infinitas Podemos usar listas para sequências finitas, por ex.: [1,2,3,4] = 1:2:3:4:[] Nesta aula vamos ver que podemos
Fundamentos da Programação de Computadores
Universidade do Minho Escola de Engenharia Departamento de Sistemas de Informação Fundamentos da Programação de Computadores Licenciatura em Tecnologias e Sistemas de Informação 1º Ano 1º Semestre Ano
Linguagens de Programação Aula 13
Linguagens de Programação Aula 13 Celso Olivete Júnior [email protected] Na aula passada Suporte para a programação orientada a objetos 2 Na aula de hoje Programação Funcional Linguagem Haskell 3 Roteiro
Sistemas Operacionais. Laboratório 1 (Ambiente de Aprendizado)
Sistemas Operacionais Laboratório 1 () Roteiro Linux em modo texto Acesso Interpretador de comandos Comandos Básicos Tratamento de Arquivos e Diretórios (Pasta*) Permissões Processos Editor de Texto Criação
PROGRAMAÇÃO de COMPUTADORES: LINGUAGEM FORTRAN 90/95
PROGRAMAÇÃO de COMPUTADORES: LINGUAGEM FORTRAN 90/95 Exercícios de revisão Lista 01: a) Monte um mapa conceitual indicando as relações entre os seguintes conceitos, no contexto do assunto visto em aula:
Guia de utilização do servidor da disciplina
Sistemas Operativos Escola de Tecnologias e Arquitectura Dep. de Ciências e Tecnologias da Informação Servidor da disciplina tigre.iul.lab Guia de utilização do servidor da disciplina 1 Introdução Os diferentes
Exercícios da cadeira de Introdução à Programação
Exercícios da cadeira de Introdução à Programação Cláudia Antunes Ana Cardoso Cachopo João Cachopo Francisco Couto António Leitão Inês Lynce César Pimentel H. Sofia Pinto Ano Lectivo 2002/2003 Parte I
Aula 5 e 6: Introdução ao shell
Programação para Redes de Computadores 17/03/014 Aula 5 e 6: Introdução ao shell Professor: Jorge H. B. Casagrande Notas de aula adaptada da original do prof. Emerson R. de Mello [email protected]
Alguns exercícios em pseudocódigo
Alguns exercícios em pseudocódigo Enunciado do problema: Escreva um programa em pseudocódigo que determine as raízes de um polinômio do segundo grau dado por a x 2 +b x+c usando o algoritmo de Báskara.
Aula 11: Modularização
Aula 11: Modularização Fernanda Passos Universidade Federal Fluminense Programação de Computadores IV Fernanda Passos (UFF) Modularização Programação de Computadores IV 1 / 37 Agenda 1 Revisão e Contexto
Aula 12: Funções. CI208 - Programação de Computadores. Prof. MSc. Diego Roberto Antunes
CI208 - Programação de Computadores Aula 12: Funções Prof. MSc. Diego Roberto Antunes [email protected] www.inf.ufpr.br/diegor Universidade Federal do Paraná Setor de Ciências Exatas Departamento de Informática
Programação Funcional. Programação Funcional LISP. Paradigma de programação baseado em Funções Matemáticas
Programação Funcional Programação Funcional Paradigma de programação baseado em Funções Matemáticas Essência de Programação: combinar funções para obter outras mais poderosas PLP 2009/1 Profa. Heloisa
LINGUAGEM C: FUNÇÕES FUNÇÃO 08/01/2018. Funções são blocos de código que podem ser nomeados e chamados de dentro de um programa.
LINGUAGEM C: FUNÇÕES Prof. André Backes FUNÇÃO Funções são blocos de código que podem ser nomeados e chamados de dentro de um programa. printf(): função que escreve na tela scanf(): função que lê o teclado
Programação de Computadores III
Programação de Computadores III Introdução ao FORTRAN Professor Hugo de Oliveira Barbalho [email protected] Material produzido pelo professor: Leandro Augusto Frata Fernandes ([email protected])
2.2.5 EXPRESSÕES - Regras para o cálculo de valores
Métodos de Programação I Departamento de Matemática, FCTUC 30 2.2.5 EXPRESSÕES - Regras para o cálculo de valores As expressões fornecidas ao computador, quer tenham variáveis, constantes ou apenas literais,
Fundamentos de Algoritmos - Aula 1
Fundamentos de Algoritmos - Aula 1 CIC/UFRGS 2006/1 Números e Aritmética 1 espécies mais populares inteiros positivos inteiros negativos frações, ou racionais reais 5-5 2/3 17/3 #i1.4142135623731 (representação
Entraremos em sistema linux para realizar algumas tarefas e aprender alguns comandos.
Entraremos em sistema linux para realizar algumas tarefas e aprender alguns comandos. Como se conectar a partir do sistema Windows: Conexão direta SSH: Putty (download) Entrando numa conta no servidor:
Métodos Computacionais. Operadores, Expressões Aritméticas e Entrada/Saída de Dados
Métodos Computacionais Operadores, Expressões Aritméticas e Entrada/Saída de Dados Tópicos da Aula Hoje aprenderemos a escrever um programa em C que pode realizar cálculos Conceito de expressão Tipos de
Universidade Federal de Ouro Preto - UFOP Departamento de Computação - DECOM Programação de Computadores I - BCC701
Universidade Federal de Ouro Preto - UFOP Departamento de Computação - DECOM Programação de Computadores I - BCC701 www.decom.ufop.br/red AULA TEÓRICA 02 1 Prof. Marcelo Luiz Silva Red CONTEÚDOS DA AULA
Aula 7: Estrutura de Decisão
Aula 7: Estrutura de Decisão Fernanda Passos Universidade Federal Fluminense Programação de Computadores IV Fernanda Passos (UFF) Estrutura de Decisão Programação de Computadores IV 1 / 27 Agenda 1 Revisão
Programação Python. Nesta aula... 1 Programação. 2 Python. Operadores e Operandos Variáveis, Expressões, Instruções Funções Ciclos Comentários
Nesta aula... 1 2 Introdução à - minor Ciência de computadores: incluí tópicos de matemática (linguagens formais para especificar ideias) engenharia (projetar, juntar componentes para formar um sistema,
Introdução à Programação. João Manuel R. S. Tavares
Introdução à Programação João Manuel R. S. Tavares Sumário 1. Ciclo de desenvolvimento de um programa; 2. Descrição de algoritmos; 3. Desenvolvimento modular de programas; 4. Estruturas de controlo de
Material Didático Unificado.
Universidade Federal de Ouro Preto - UFOP Departamento de Computação - DECOM Comissão da Disciplina Programação de Computadores I CDPCI Programação de Computadores I BCC701 www.decom.ufop.br/bcc701 Material
Introdução à Linguagem C Variáveis e Expressões
INF1005: Programação 1 Introdução à Linguagem C Variáveis e Expressões 08/03/10 (c) Paula Rodrigues 1 Tópicos Principais Programando em C Funções Variáveis Define Operadores e Expressões Entrada e Saída
UNIVERSIDADE FEDERAL RURAL DO SEMI-ÁRIDO CURSO: CIÊNCIA DA COMPUTAÇÃO. Prof.ª Danielle Casillo
UNIVERSIDADE FEDERAL RURAL DO SEMI-ÁRIDO CURSO: CIÊNCIA DA COMPUTAÇÃO TEORIA DA COMPUTAÇÃO Aula 04 Programa Recursivo e Máquinas Prof.ª Danielle Casillo Funções recursivas Alguma função é recursiva quando
Introdução à Programação. Operadores, Expressões Aritméticas e Entrada/Saída de Dados
Introdução à Programação Operadores, Expressões Aritméticas e Entrada/Saída de Dados Programa em C #include int main main ( ) { Palavras Reservadas } float celsius ; float farenheit ; celsius
Compilador de LP3 para C3E e P3
Compilador de LP3 para C3E e P3 Luís Gil 1 13 de Junho de 2005 1 estudante de Ciências Informáticas no Instituto Superior Técnico 1 Introdução Este relatório descreve a sintaxe e a semântica da Linguagem
Informática no Ensino de Matemática Prof. José Carlos de Souza Junior
Informática no Ensino de Matemática Prof. José Carlos de Souza Junior http://www.unifal-mg.edu.br/matematica/?q=disc jc Aula 03 ATIVIDADE 01 (a) Sejam u = (a b)/(a + b), v = (b c)/(b + c) e w = (c a)/(c
Procalc v1.0. Versão Utilizador (Manual de Utilizador)
Procalc v1.0 Versão Utilizador (Manual de Utilizador) Conteúdo Procalc... 4 Botões Numéricos... 5 Funções Básicas... 6 Funções avançadas... 7 Logaritmo... 7 Logaritmo Natural... 7 Expoente... 7 Factorial...
4. Constantes. Constantes pré-definidas
4. Constantes Constantes pré-definidas O PHP possui algumas constantes pré-definidas, indicando a versão do PHP, o Sistema Operacional do servidor, o arquivo em execução, e diversas outras informações.
Exercícios para Fundamentos da Programação
Exercícios para Fundamentos da Programação Fausto Almeida, Cláudia Antunes, Ana Cardoso-Cachopo, Pedro Amaro de Matos, Francisco Saraiva de Melo Departamento de Engenharia Informática Instituto Superior
1 Expressões, valores e tipos 1. 2 Variáveis e atribuições 5. cálculo de expressões segue a estrutura de parênteses e as prioridades dos operadores
Nesta aula... Conteúdo 1 Expressões, valores e tipos 1 2 Variáveis e atribuições 5 1 Expressões, valores e tipos Expressões e valores Tipos programas calculam expressões para produzir valores cálculo de
INSTRUÇÕES DE REPETIÇÃO
Cursos: Análise, Ciência da Computação e Sistemas de Informação Programação I - Prof. Aníbal Notas de aula 6 INSTRUÇÕES DE REPETIÇÃO As instruções de repetição permitem fazer com que a execução de uma
