Funcional IV: listas e funções de ordem superior

Documentos relacionados
Racket Básico: Tipos e QuickCheck

Funcional II: recursão e iteração

Estudo de caso: codificação de Huffman (parte II)

Funcional V: estruturas de dados puramente funcionais

Paralelismo de dados com futures

Fundamentos de Programação

Programação lógica: operadores, repe ções e listas

Fundamentos de Programação

Exercícios para Fundamentos da Programação Utilizando Múltiplos Paradigmas

é uma proposição verdadeira. tal que: 2 n N k, Φ(n) = Φ(n + 1) é uma proposição verdadeira. com n N k, tal que:

Aula prática 5. Funções Recursivas

MATEMÁTICA 1 MÓDULO 2. Divisibilidade. Professor Matheus Secco

;(define conta-folhas ; (lambda ( ) ; (cond ; ( ( ) ) ; ( (and ) ) ; ( else ; ) ) ))

a) Falsa. Por exemplo, para n = 2, temos 3n = 3 2 = 6, ou seja, um número par.

Um algoritmo deve conter passos não ambíguos, executáveis e que sejam terminados quando seguidos.

Inteligência Artificial

Aula 3: Algoritmos: Formalização e Construção

Aula 2: Algoritmos: Intuição

Pedro Vasconcelos DCC/FCUP. Programação Funcional 3 a Aula Definição de funções

Decomposição de um número composto. Todo número composto pode ser decomposto em fatores primos Ex: = 2 2 X 3 X 5 X 7

Fundamentos de Programação

ESTRUTURAS DE REPETIÇÃO - PARTE 2

Matemática para Ciência de Computadores

Naturais. Paradigma de Programação Funcional. Marco A L Barbosa

Waldemar Celes e Roberto Ierusalimschy. 29 de Fevereiro de 2012

Lista de Exercícios sobre Recursividade

Roteiro da segunda aula presencial - ME

Matemática Discreta. Introdução à Teoria de Números - Exercícios 1 o ano /2011

Capítulo V : A Linguagem Pascal Um Tipo Estruturado de Dados: o array 18. Para limite de n até 2 (* passagens de 1 até (n-1) *)

Matemática Discreta. Fundamentos e Conceitos da Teoria dos Números. Universidade do Estado de Mato Grosso. 4 de setembro de 2017

Elementos de Matemática Finita

CIC 111 Análise e Projeto de Algoritmos II

USANDO UM MÉTODO INDUTIVO PARA RESOLVER PROBLEMAS. Bruno Maffeo Departamento de Informática PUC-Rio

Estruturas de controle sequencial e condicional

Introdução à Programação. Ciclos 1ª parte

Definição. Diremos que um número inteiro d é um divisor de outro inteiro a, se a é múltiplo de d; ou seja, se a = d c, para algum inteiro c.

Algoritmos e Lógica de Programação. 6ª Lista de Exercícios Comandos de Repetição

Tipo de argumentos. valor. argumentos

Exercícios: Árvores. Universidade Federal de Uberlândia - UFU Faculdade de Computação - FACOM Lista de exercícios de estrutura de dados em linguagem C

Anexo A. Resumo dos principais procedimentos do Scheme

Fundamentos de Programação

ALGORITMO DE EUCLIDES

Programação imperativa

7 a Lista de Exercícios Assunto: Funções e passagem por referência com vetor e matriz (Tópico 7)

ALGORITMOS AVANÇADOS UNIDADE II Recursividade. Luiz Leão

Fundamentos de Programação

notas de aula versão 1 - Jerônimo C. Pellegrini notas de aula versão 1 11 de fevereiro de 2011

Programação I Aula 19 Aritmética com racionais Pedro Vasconcelos DCC/FCUP

Linguagens de Programação

Aula 7 - Mais problemas com inteiros

Universidade Federal do Espírito Santo Centro de Ciências Agrárias CCA UFES Departamento de Computação. Teoria dos Números

Lógica de Hoare. Abordagem que usaremos: aplicar o método de Hoare sobre uma linguagem de programação imperativa simplificada.

Lógica de Programação I

Procedimento. Função. Selecção Condicional - a instrução if-then-else. expressão if lógica then instrução else instrução

Gabarito Lista 2, Álgebra I

Estudo de caso: codificação de Huffman (parte I)

Textos de apoio às aulas práticas. Jaime Ramos, Francisco Miguel Dionísio

Fundamentos de Programação

Bruno Hott Algoritmos e Estruturas de Dados I DECSI UFOP. Recursividade

Fundamentos de Programação Instituto Federal de Educação, Ciência e Tecnologia do Rio Grande do Norte 15 de maio de 2018.

D 7 C 4 U 5. MATEMÁTICA Revisão Geral Aula 1 - Parte 1. Professor Me. Álvaro Emílio Leite. Valor posicional dos números. milésimos décimos.

Layout. Módulos. Normalmente, cada módulo está armazenado num ficheiro com o mesmo nome do módulo. Exemplo.hs

PCI- Estrutura de Repetição II. Profa. Mercedes Gonzales Márquez

Alguns exercícios em pseudocódigo

Programação e Computação para Arquitectura 2012/2013

Universidade Federal do Rio Grande Bacharelado em Matemática Aplicada Disciplina de Algoritmos e Programação de Computadores

Teorema Chinês dos Restos. Tópicos Adicionais

SSC300- Linguagens de Programação e Aplicações Profa Vânia de Oliveira Neves. ICMC/USP São Carlos

Lista de Revisão Prova 1

Linguagem e Técnicas em Programação. Gilson de Souza Carvalho

Paradigmas de Programação

Programação Estruturada

Números Inteiros Algoritmo da Divisão e suas Aplicações

controle de fluxo repetições iterativas

Divisibilidade e Números primos. George Darmiton da Cunha Cavalcanti CIn - UFPE

MATEMÁTICA. Aula 4. Professor : Dêner Rocha. Monster Concursos 1

Equações Diofantinas + = polinómios conhecidos polinómios desconhecidos

CCM0118 Computação I

Vejamos agora mais alguns exemplos de problemas envolvendo seqüência de números.

Listas Estáticas. SCC Algoritmos e Estruturas de Dados I. Prof. Fernando V. Paulovich. *Baseado no material do Prof.

Centro de Informá-ca Universidade Federal de Pernambuco. Vinicius Cardoso Garcia 2011 Vinicius Cardoso Garcia

Abstração de dados. Pedro Kröger. 5 de outubro de Um índice bibliográco poderia ser armazenado dessa maneira:

Análise e Desenvolvimento de Algoritmos (2006/2007)

Programação de Computadores I BCC 701 Lista de Exercícios Módulo

Pedro Vasconcelos DCC/FCUP. Programação Funcional 5 a Aula Definições recursivas

Árvores Binárias de Busca

Recursividade. David Menotti Algoritmos e Estruturas de Dados II DInf UFPR

1 TESTE OPÇÃO II - TEORIA DE NÚMEROS COMPUTACIONAL

Exercícios da cadeira de Introdução à Programação

Estruturas de Repetição

Lista de Exercícios Estrutura de Repetição

Exercícios Repetição

Trabalho de Programação Funcional Linguagem Scheme

INE5403 FUNDAMENTOS DE MATEMÁTICA DISCRETA

Árvores Binárias. SCC Algoritmos e Estruturas de Dados I. Prof. Fernando V. Paulovich

ESTRUTURAS DE DADOS E ALGORITMOS APRESENTAÇÃO DO CURSO E INTRODUÇÃO

Python Funções. Introdução à Programação SI1

PK - Public Key RSA. Segurança RSA

Transcrição:

Funcional IV: listas e funções de ordem superior Profs. Diogo S. Mar ns e Emilio Francesquini {santana.mar ns,e.francesquini}@ufabc.edu.br MCTA016 - Paradigmas de Programação (Prá ca) 26 de junho de 2018 Crédito de parte das imagens, a menos se especificado: Wikipedia

Obje vos TODO 1 / 28

Parte 1: primalidade sem listas 2 / 28

Exercício 1 Construa um procedimento que teste se um número primo. 3 / 28

Exercício 1 Solução 1 Testa pra camente todos os antecessores como divisores: 1 (define (divides a b) 2 (= (modulo a b) 0)) 3 4 (define (prime? n) 5 (if (< n 2) 6 #f 7 (prime-f? n 2))) 8 9 ; prime test with exhaustive divisor search 10 (define (prime-f? n i) 11 (cond [(= n i) ] 12 [( divides n i) #f] 13 [else (prime-f? n (+ i 1))])) Para números grandes, o teste torna-se inviável: > (time (prime? 2147483647)) cpu time: 36347 real time: 36332 gc time: 0 4 / 28

Exercício 1 Solução 2 Podemos diminuir o espaço de busca se usarmos a propriedade: Todo número composto tem um fator que é menor ou igual à sua raiz quadrada¹ 1 (define (prime-a? n) 2 (let prime-a-i ([i 2]) 3 (cond [(> (* i i) n) ] 4 [( divides n i) #f] 5 [else (prime-a-i (+ i 1))]))) ¹Se n é composto, é possível fatorá-lo como n = ab, sendo a > 1 e b < n. Se a > n e b > n, então n = n n < a b = n, que é uma contradição. 5 / 28

Exercício 1 Solução 3 Outra propriedade interessamte: Se o número não é divisível por 2, também não será divisível por qualquer múl plo de 2 Com isso, podemos eliminar todos os números pares do nosso teste 1 (define (prime-b? n) 2 (cond [(= n 2) ] 3 [( divides n 2) #f] 4 [else (let prime-b-i ([i 3]) 5 (cond [(> (* i i) n) ] 6 [( divides n i) #f] 7 [else (prime-b-i (+ i 2))]))])) 6 / 28

Exercício 1 Soluções 1, 2 e 3: medição de tempo de execução > (time (prime? 6700417)) cpu time: 117 real time: 118 gc time: 0 > (time (prime -a? 6700417)) cpu time: 0 real time: 0 gc time: 0 > (time (prime -a? 67280421310721)) cpu time: 145 real time: 145 gc time: 0 > (time (prime -a? 2147483647)) cpu time: 1 real time: 0 gc time: 0 > (time (prime -b? 6700417)) cpu time: 1 real time: 0 gc time: 0 > (time (prime -b? 67280421310721)) cpu time: 73 real time: 73 gc time: 0 > (time (prime -b? 2147483647)) cpu time: 1 real time: 1 gc time: 0 7 / 28

Exercício 2 No teste de primalidade, podemos diminuir ainda mais o espaço de busca por divisores se considerarmos a seguintes propriedades: Todo número primo, exceto 2 e 3, tem a forma 6k ± 1 ² Todo número composto tem um fator primo Consequentemente, caso n não seja 2 ou 3, nem seja divisível por 2 ou 3, basta usarmos como divisores os primos gerados por essa sequência, considerando também a propriedade que se n é composto, então tem um divisor menor ou igual que n. Um exemplo de expansão da sequência é 5, 7, 11, 13, 17, 19, 23, 25,... 1 Construa uma função que teste a primalidade com base nessas propriedades 2 Faça testes de tempo de execução comparando sua implementação com as vistas anteriormente, considerando inteiros grandes ²Atenção: isso não implica que todo número 6k ± 1 é primo. 8 / 28

Exercício 2: solução Solução 1 (define (prime? n) 2 (prime-c? n)) 3 4 (define (prime-c? n) 5 (cond [(= n 2) ] 6 [(= n 3) ] 7 [else (let loop ([k 1] [i 2] [j 3]) 8 (cond [(> (* i i) n) ] 9 [( divides n i) #f] 10 [( divides n j) #f] 11 [else (loop 12 (+ k 1) 13 (- (* 6 k) 1) 14 (+ (* 6 k) 1))]))])) 9 / 28

Exercício 2: solução Teste de desempenho 1 (time (prime-a? 6700417)) 2 (time (prime-a? 67280421310721)) 3 (time (prime-a? 2147483647)) 4 5 (display "\n") 6 7 (time (prime-b? 6700417)) 8 (time (prime-b? 67280421310721)) 9 (time (prime-b? 2147483647)) 10 11 (display "\n") 12 13 (time (prime-c? 6700417)) 14 (time (prime-c? 67280421310721)) 15 (time (prime-c? 2147483647)) $ racket primes.rkt cpu time: 0 real time: 0 gc time: 0 cpu time: 147 real time: 147 gc time: 0 cpu time: 1 real time: 1 gc time: 0 cpu time: 0 real time: 0 gc time: 0 cpu time: 76 real time: 75 gc time: 0 cpu time: 0 real time: 1 gc time: 0 cpu time: 0 real time: 0 gc time: 0 cpu time: 27 real time: 27 gc time: 0 cpu time: 0 real time: 0 gc time: 0 10 / 28

Exercício 2 Testes 1 ; primes in [2,200] 2 (define primes '(2 3 5 7 11 3 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 4 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 5 179 181 191 193 197 199)) 6 ; composites in [1,200] 7 (define composites '(4 6 8 9 8 12 14 15 16 18 20 21 22 24 25 26 27 28 30 32 33 34 35 36 9 38 39 40 42 44 45 46 48 49 50 51 52 54 55 56 57 58 60 62 10 63 64 65 66 68 69 70 72 74 75 76 77 78 80 81 82 84 85 86 11 87 88 90 91 92 93 94 95 96 98 99 12 100 102 104 105 106 108 110 111 112 114 115 116 117 118 13 119 120 121 122 123 124 125 126 128 129 130 132 133 134 14 135 136 138 140 141 142 143 144 145 146 147 148 150 152 15 153 154 155 156 158 159 160 161 162 164 165 166 168 169 16 170 171 172 174 175 176 177 178 180 182 183 184 185 186 17 187 188 189 190 192 194 195 196 198 200)) 18 (define primes-suite 19 (test-suite 20 "Test primality related operations" 21 (check-true (andmap prime? primes)) 22 (check-false (ormap prime? composites)) 23 (run-tests primes-suite) $ racket primes -tests.rkt 2 success(es) 0 failure(s) 0 error(s) 2 test(s) run 11 / 28

Parte 2: primalidade com listas 12 / 28

Exercício 3 Construa o procedimento (gen-primes n) cujo valor é uma lista com todos os números primos em [2, n]. Exemplo de chamada: > (gen-primes 20) '(2 3 5 7 11 13 17 19) 13 / 28

Exercício 3 Solução 1³: testes baseados em divisores ímpares com geração de listas intermediárias 1 (define (divisivel? a b) 2 (= (modulo a b) 0)) 3 4 (define (possiveis-divisores a) 5 (cons 2 6 (cdr (build-list (floor (/ a 2)) 7 (lambda(x) (add1 (* x 2))))))) 8 9 (define (primo? n) 10 (or (= n 2) (and 11 (> n 2) 12 (not (ormap 13 (lambda (x) (divisivel? n x)) 14 (possiveis-divisores n)))))) 15 16 (define (primos-ate n) 17 (filter primo? (build-list (sub1 n) (lambda (x) (+ 2 x))))) ³Código-fonte correspondente à semana 2 14 / 28

Exercício 3 Solução 1 testes de propriedades e desempenho 1 (define prop-primos-ate 2 (property 3 ([n (choose-integer 2 (random 10000))]) 4 (andmap primo? (primos-ate n)))) > (primos -ate 40) '(2 3 5 7 11 13 17 19 23 29 31 37) $ racket primos.rkt OK, passed 100 tests. > (time (let () (primos -ate 10000) (void))) cpu time: 612 real time: 611 gc time: 10 15 / 28

Exercício 3 Solução 2: tenta vas de divisão exaus vas Vamos diminuir o uso de memória evitando a geração de listas intermediárias: 1 (define (gen-primes-a n) 2 (let gen-primes-a-i ([i 2] [p null]) 3 (cond [(> i n) (reverse p)] 4 [(prime? i) (gen-primes-a-i (+ i 1) (cons i p))] 5 [else (gen-primes-a-i (+ i 1) p)]))) > (gen-primes -a 20) '(2 3 5 7 11 13 17 19) Porém, estamos gerando divisores sequenciais, é possível melhorar 16 / 28

Exercício 3 Solução 3: Usando propriedade 6k ± 1 A propriedade 6k ± 1 gera menos divisores do que o conjunto dos possíveis divisores ímpares Adicionalmente, gera números u lizando um padrão regular: 1 (define (gen-pair k) 2 (list (- (* 6 k) 1) (+ (* 6 k) 1))) 3 4 (define (gen-wheel-pairs n) 5 (let rec ([k 1]) 6 (if (= k n) 7 null 8 (cons (gen-pair k) (rec (+ k 1)))))) > (gen-wheel -pairs 10) '((5 7) (11 13) (17 19) (23 25) (29 31) (35 37) (41 43) (47 49) (53 55)) Para cada par (i k, j k ): j k i k = 2 i k+1 j k = 4 17 / 28

Exercício 3 Solução 2: Usando propriedade 6k ± 1 Algoritmo usando as razões do slide anterior: 1 ; cons in primes only if i is prime 2 (define (cons-prime i primes) 3 (if (prime? i) 4 (cons i primes) 5 primes)) 6 7 ; prime enumeration based on 6k+-1 property 8 (define (gen-primes-b n) 9 (cond [(< n 2) null] 10 [(= n 2) (list 2)] 11 [(= n 3) (list 2 3)] 12 [else (let loop ([i 5] [k 2] [primes '(3 2)]) 13 (cond [(> i n) (reverse primes)] 14 [(= k 2) (loop (+ i k) 4 (cons-prime i primes))] 15 [else (loop (+ i k) 2 (cons-prime i primes))]))])) > (gen-primes -b 20) '(2 3 5 7 11 13 17 19) 18 / 28

Exercício 3 Soluções 2 e 3: testes 1 (require rackunit "primes.rkt") 2 (require rackunit/text-ui) 3 4 ; primes in [2,200] 5 (define primes '(2 3 5 7 11 6 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 7 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 8 179 181 191 193 197 199)) 9 ; composites in [1,200] 10 (define composites '(4 6 8 9 11 12 14 15 16 18 20 21 22 24 25 26 27 28 30 32 33 34 35 36 12 38 39 40 42 44 45 46 48 49 50 51 52 54 55 56 57 58 60 62 13 63 64 65 66 68 69 70 72 74 75 76 77 78 80 81 82 84 85 86 14 87 88 90 91 92 93 94 95 96 98 99 15 100 102 104 105 106 108 110 111 112 114 115 116 117 118 16 119 120 121 122 123 124 125 126 128 129 130 132 133 134 17 135 136 138 140 141 142 143 144 145 146 147 148 150 152 18 153 154 155 156 158 159 160 161 162 164 165 166 168 169 19 170 171 172 174 175 176 177 178 180 182 183 184 185 186 20 187 188 189 190 192 194 195 196 198 200)) 21 22 (define primes-suite 23 (test-suite 24 "Test with a list of primes" 25 (check-true (andmap prime? primes)) 26 (check-false (ormap prime? composites)) 27 (check-true (equal? (gen-primes-a 200) primes)) 28 (check-true (equal? (gen-primes-b 200) primes)))) 29 30 (run-tests primes-suite) $ racket primes -tests.rkt 4 success(es) 0 failure(s) 0 error(s) 4 test(s) run 19 / 28

Exercício 3 Soluções 1, 2 e 3: testes de tempo de execução > (time (let () (gen-primes -a 10000) (void))) cpu time: 3 real time: 3 gc time: 0 > (time (let () (gen-primes -b 10000) (void))) cpu time: 3 real time: 3 gc time: 0 > (time (let () (primos -ate 10000) (void))) cpu time: 612 real time: 611 gc time: 10 > (time (let () (gen-primes -a 6700417) (void))) cpu time: 6200 real time: 6197 gc time: 19 > (time (let () (gen-primes -b 6700417) (void))) cpu time: 5971 real time: 5969 gc time: 21 Exercício 4: Por quê as soluções 2 e 3 diferem pouco no tempo de execução? Jus fique com base na análise do algoritmo ou com exemplos de traço de execução. 20 / 28

Exercício 5 Construa um procedimento que fatore um inteiro posi vo fornecido como parâmetro. O valor do procedimento deve ser uma lista de todos os fatores. Exemplo: > (factorize 123) '(3 41) > (factorize 438) '(2 3 73) > (factorize 428) '(2 2 107) > (factorize 448) '(2 2 2 2 2 2 7) 21 / 28

Exercício 5 Solução 1 (define (factorize n) 2 (let loop ([n n] [factors null] [primes (gen-primes (sqrt n))]) 3 (cond [(< n 2) (reverse factors)] 4 [(null? primes) (reverse (cons n factors))] 5 [(divides n (car primes)) 6 (loop (quotient n (car primes)) (cons (car primes) factors) primes)] 7 [else (loop n factors (cdr primes))]))) 22 / 28

Exercício 5 Testes 1 (define factors '( (5. (5)) 2 (...) 3 (255. (3 5 17)) 4 (256. (2 2 2 2 2 2 2 2)) 5 (257. (257)) 6 (258. (2 3 43)) 7 (259. (7 37)) 8 (...) 9 (776. (2 2 2 97)) 10 (777. (3 7 37)) 11 (778. (2 389)) 12 (779. (19 41)) 13 (780. (2 2 3 5 13)) 14 (781. (11 71)))) 15 (define primes-suite 16 (test-suite 17 "Test primality related operations" 18 (...) 19 (test-case 20 "Test prime factoring" 21 (define (test-factors pair) 22 (equal? (factorize (car pair)) (cdr pair))) 23 (check-true (andmap test-factors factors))) 24 (...))) 25 26 (run-tests primes-suite) $ racket primes -tests.rkt 5 success(es) 0 failure(s) 0 error(s) 5 test(s) run 23 / 28

Exercícios para entregar 24 / 28

Exercício 8 Com base na solução 1 para enumeração de primos, resolva os itens a seguir. 6. Crie testes u lizando o QuickCheck para verificar as funções divisível? e possiveisdivisores. Além disto, crie um teste adicional para a função primos-ate que verifica se a função obedece o parâmetro n, ou seja, que não são devolvidos primos maiores que n. 7. O n-ésimo número de Mersenne é dado pela fórmula M n = 2 n 1. Desde a an guidade sabe-se que M 2, M 3, M 5 e M 7 são primos. Como 2, 3, 5 e 7 são primos, conjecturou-se que para todo p primo, então M p também seria primo. U lizando o QuickCheck mostre que este não é o caso. 25 / 28

Exercício 9 O máximo fator comum ou máximo divisor comum (mdc) de um dois ou mais números é o produto de todos os fatores primos comuns a esses números. 1 Construa (mdc x y) com base nessa propriedade. Você pode usar a função factorize. Pode usar também a função lset-intersection da srfi/1. 2 Ao aplicar factorize consecu vamente para dois números, cada aplicação gera uma nova lista de primos, porém as duas listas geradas apresentarão intersecção potencialmente grande se os números forem próximos (i.e. gero primos repe dos desnecessariamente). Por exemplo, mdc(68,156) => 4, mas (gen-primes (sqrt 68)) => '(2 3 5 7) e (gen-primes (sqrt 156)) = '(2 3 5 7 11). Trate esse problema gerando uma única lista de primos, apenas para o maior dos números. 3 Outra estratégia para calcular mdc é o algoritmo de Euclides, que tem a seguinte definição itera va: se x é maior que y, então se y divide x, então o mdc de x e y é y; caso contrário, o mdc de x e y é o mesmo que o mdc de (modulo x y) e y. Implemente o algoritmo de Euclides e compare o desempenho (em tempo de execução) com o algoritmo do item anterior. 4 Modifique o algoritmo de Euclides para que receba uma lista com uma quan dade arbitrária de números e determine o mdc entre esses números. 26 / 28

Exercício 10 O mínimo múl plo comum (mmc) de uma lista de números pode ser computado pela divisão sucessiva dos elementos da lista pela sequência de números primos, sempre que seja possível dividir um dos elementos da lista por um primo, até que todos os elementos da lista sejam 1. O mmc é produto de todos os divisores primos u lizados. Exemplo: (4 7 12 21 42) 2 (2 7 6 21 21) 2 (1 7 3 21 21) 3 (1 7 1 7 7) 7 (1 1 1 1 1) mmc(4,7,12,21,42) = 2 * 2 * 3 * 7 = 84 1 Construa uma função que determine o mmc pelo método descrito acima. 2 Uma definição alterna va de mmc é estabelecida pela fórmula mmc(a, b) = a b. U lize o algoritmo de Euclides para construir uma mdc(a,b) função que determine o mmc de acordo com a fórmula. Compare o desempenho com a solução do item anterior. 27 / 28

Recursos recomendados Pairs and Lists. Racket Guide. URL: https://docs.racket-lang.org/guide/pairs.html 28 / 28

Funcional IV: listas e funções de ordem superior Profs. Diogo S. Mar ns e Emilio Francesquini {santana.mar ns,e.francesquini}@ufabc.edu.br MCTA016 - Paradigmas de Programação (Prá ca) 26 de junho de 2018 Crédito de parte das imagens, a menos se especificado: Wikipedia