Buscar

Paradigmas de Linguagens de Programação - Lista 1 2016 2

Prévia do material em texto

1ª Lista de Paradigmas de Linguagens Computacionais 
Lista de Exercícios do Paradigma Funcional 
 
CIn – UFPE (2016.2) 
Disponível em: 30/08/2016 
 
Professores: 
André Luís de Medeiros Santos (alms@cin.ufpe.br) 
Henrique Emanuel Mostaert Rebêlo (hemr@cin.ufpe.br) 
 
Monitores: 
Álvaro Arthur Canto Sabino de Miranda Costa (aacsmc@cin.ufpe.br) 
Gustavo de Oliveira Feitosa (gof@cin.ufpe.br) 
Ihago Henrique Lucena e Silva (ihls@cin.ufpe.br) 
Luiz Henrique de Souza (lhs2@cin.ufpe.br) 
Renato Vieira Leite de Barros (rvlb@cin.ufpe.br) 
Roberto Costa Fernandes (rcf6@cin.ufpe.br) 
 
1. Sobre o paradigma funcional, desenvolva os seguintes conceitos: 
a) Transparência referencial 
b) Funções de alta ordem 
c) Currying 
d) Lambda Cálculo 
 
2. Implemente uma função que, dado 3 números inteiros, retorne um booleano 
indicando se pelo menos dois deles são números ímpares. 
 
3. Defina a função logic :: (Bool, Bool) -> (Bool, Bool, Bool) que tem como 
finalidade testar a tupla de entrada para cada um dos operadores lógicos 
(and, or, xor) e gerar uma tupla na qual seus membros são a resposta de cada teste. 
 
 
 
 
Exemplos: 
Main> logic (True, True) 
(True, True, False) 
 
Main> logic (False, True) 
(False, True, True) 
 
4. Crie uma função: triangulo :: (Int, Int, Int) -> (String, Int), que, dado 3 inteiros, 
verifique se os mesmos podem ser os lados de um triângulo. Se for possível forma-
lo retorne uma dupla com o tipo do triângulo formado (com relação às arestas) e o 
perímetro do mesmo, caso contrário imprima: (“Impossivel”, 0). 
 
Exemplos: 
Main> triangulo (7, 7, 11) 
(“Isosceles”, 25) 
 
Main> triangulo (7, 7, 7) 
(“Equilatero”, 21) 
 
Main> triangulo (7, 7, 15) 
(“Impossivel”, 0) 
 
5. 
a) Defina o tipo Ponto como sinônimo de uma tupla com três Float. Defina, 
também, a função distancia :: Ponto -> Ponto -> Float, que calcula a distância entre 
três pontos em um espaço tridimensional. 
 
Exemplo: 
Main> distancia (0, 0, 0) (1, 1, 1) 
1.7320508 
 
b) Agora defina o tipo Esfera como sinônimo de um Ponto central e um Float como 
raio. Defina, ainda, a função estaContido :: Esfera -> Ponto -> Bool, que diz se um 
ponto dado está contido ou não na superfície de uma esfera. 
 
 
 
Exemplos: 
Main> estaContido ((0, 0, 0), 1) (1, 1, 1) 
False 
 
Main> estaContido ((0, 0, 0), 1) (0, 0, 1) 
True 
 
6. Dado o limite inferior e o superior de um intervalo e o seu incremento, 
implemente, sem a utilização de listas, a função somaIntervalo :: Int -> Int -> Int -> 
Int que indique a soma dos números que pertencem a este intervalo. 
 
Exemplos: 
Main> somaIntervalo 1 7 2 
16 
 
Main> somaIntervalo 10 26 3 
105 
 
7. Implemente a função sumDigits :: Int -> Int cuja finalidade seja somar todos os 
dígitos de um número natural. 
 
Exemplos: 
Main> sumDigits 9182 
20 
 
Main> sumDigits 1002 
3 
 
8. Implemente a função: nPrimo :: Int -> Int, que encontre o N-ésimo número 
primo natural. A função deverá ser implementada de forma recursiva e sem a 
utilização de listas. 
 
Exemplos: 
Main> nPrimo 1 
2 
 
Main> nPrimo 2 
3 
 
Main> nPrimo 5 
11 
 
Main> nPrimo 750 
5693 
 
9. Devido à intensa quantidade de posts de política no Facebook, durante o período 
das eleições 2014, você decidiu que não gostaria de ver qualquer post que falasse 
de Dilma ou Aécio. Para isso você vai criar uma função limpaTimeline :: [String] -> 
[String] que recebe uma lista de posts e não mostra os que citam a palavra “Dilma” 
e/ou “Aecio”. 
 
Dica: 
Importe a biblioteca Data.List e utilize a função isInfixOf. Para importar a 
biblioteca, escreva no começo do arquivo o seguinte trecho de código: 
import Data.List 
 
A função isInfixOf :: Eq a => [a] -> [a] -> Bool pega duas listas e retorna True se a 
primeira lista está completamente contida em qualquer lugar da segunda lista. 
 
Exemplos: 
Main> limpaTimeline [(“Maria: Votarei em Dilma”), (“Pedro: Eu voto em Aecio”), 
(“Carolina: Hoje eh dia de votar”)] 
 
[("Carolina: Hoje eh dia de votar")] 
 
Main> limpaTimeline [(“Jose: Oi, eu sou o Goku!”), (“Melissa: Dilma x Aecio = Vou 
votar em branco”), (“Luigi: #partiu Votar”)] 
 
[(“Jose: Oi, eu sou o Goku!”), (“Luigi: #partiu Votar”)] 
 
10. Implemente em Haskell o algoritmo de ordenação Mergesort para ordenar uma 
lista de números inteiros. 
 
11. Combinação é um subconjunto com p elementos de um conjunto 
possivelmente maior com n elementos, onde p <= n. A combinação dos elementos 
[1, 2, 3], por exemplo, pode gerar os seguintes agrupamentos: [], [1], [2], [3], 
[1, 2], [1, 3], [2, 3] e [1, 2, 3]. Repare que a ordem dos elementos em cada 
agrupamento é irrelevante, logo mudar a ordem dos elementos não gera 
combinações diferentes. 
 
Crie uma função combinacoes :: [Int] -> [[Int]] para gerar todas as possíveis 
combinações sem repetição dos inteiros de um grupo de entrada. 
 
Exemplos: 
Main> combinacoes [81, 25] 
[[], [81], [25], [81, 25]] 
 
Main> combinacoes [1, 2, 3] 
[[], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]] 
 
Main> combinacoes [10, -80, 14, 16] 
[[], [10], [-80], [10, -80], [14], [10, 14], [-80, 14], [10, -80, 14], [16], [10, 16], 
[-80, 16], [10, -80, 16], [14, 16], [10, 14, 16], [-80, 14, 16], [10, -80, 14, 16]] 
 
12. Escreva uma função: reduz1 :: [Int] -> [Int], que receba uma lista ordenada e 
para cada número que apareça n vezes, deverá aparecer (n-1) vezes na lista 
retornada. Utilize obrigatoriamente compreensão de listas (Ou seja, sem utilizar 
recursão) para implementar reduz1. 
 
Exemplo: 
Main> reduz1 [1, 1, 2, 2, 2, 2, 5, 9] 
[1, 2, 2, 2] 
 
13. O professor Carvalho precisa de uma função para catalogar todos os 
pokemons que ele encontrou até agora e saber quais faltam para sua coleção. 
Utilizando compreensão de listas, crie uma função catalogoPokemon :: Int -> Int -> 
[String] que recebe o intervalo do número dos pokemons que serão catalogados e 
constrói uma lista com todos os pokemons encontrados e desconhecidos naquele 
intervalo. 
 
O banco de dados do professor Carvalho é dado abaixo. 
 
pokemon :: Int -> String 
pokemon 1 = “Bulbasaur” 
pokemon 2 = “Ivysaur” 
pokemon 3 = “Venusaur” 
pokemon 4 = “Charmander” 
pokemon 5 = “Charmeleon” 
pokemon 6 = “Charizard” 
pokemon 7 = “Squirtle” 
pokemon 8 = “Wartortle” 
pokemon 9 = “Blastoise” 
pokemon 12 = “Butterfree” 
pokemon _ = “Unknown” 
 
Exemplos: 
Main> catalogoPokemon 1 9 
[“Bulbasaur”, “Ivysaur”, “Venusaur”, “Charmander”, “Charmeleon”, “Charizard”, 
“Squirtle”, “Wartortle”, “Blastoise”] 
 
Main> catalogoPokemon 7 12 
[“Squirtle”, “Wartortle”, “Blastoise”, “Unknown”, “Unknown”, “Butterfree”] 
 
14. Implemente uma função capaz de, dado um par de funções, executar um “fold 
matricial” comprimindo os elementos de uma determinada linha usando uma das 
funções e os resultados usando a outra. 
 
Exemplos: 
Main> foldMatrix (*) (+) [[1, 2, 3], [1, 2, 3]] 
12 
 
Main> foldMatrix (+) (*) [[1, 2, 3], [1, 2, 3]] 
36 
 
15. Crie a função (>.>) :: (a -> b) -> (b -> d) -> (a -> d) que receba 2 funções e 
retorne uma terceira função que é a aplicação sucessiva delas. 
 
Main> ((div 2) >.> (2*)) 2 
2 
 
Main> ((2*) >.> (div 2)) 2 
0 
 
16. Implemente a função multiFilter :: [(a -> Bool)] -> [a] -> [a], uma versão da 
função filter que recebe uma lista de funções e uma lista de um tipo qualquer, e 
retorna uma lista com os elementos filtrados por todas as funções da lista de 
funções.Exemplos: 
Main> multiFilter [even, (\x -> (mod x 5)==0)] [1..100] 
[10, 20, 30, 40, 50, 60, 70, 80, 90, 100] 
 
Main> multiFilter [] “Janeiro” 
“Janeiro” 
 
17. Defina uma função g ::[Int] -> Bool que verifica que todo elemento de uma 
lista que está entre 0 e 100 (inclusive) é par. Utilize as funções map, filter e foldr. 
 
Exemplos: 
Main> g [0, 26, 153, 72, 68, 8] 
True 
 
Main> g [1, 12, 153, 73, 9] 
False 
 
Main> g [ ] 
True 
 
Main> g [1, 255] 
False 
 
 
 
18. Implemente a função: divs :: [Int] -> Int -> Int -> (Bool, Bool), que dada uma 
lista de inteiros, devolva uma tupla onde o primeiro membro indica se todos os 
números pares da lista são divisíveis pelo segundo argumento e o segundo membro 
indica se todos os números ímpares da lista são divisíveis pelo terceiro argumento. 
Para implementar a função divs, utilize obrigatoriamente as funções map, filter e 
alguma função fold (foldr, foldl, foldr1 ou foldl1). 
 
Exemplo: 
Main> divs [5, 6, 18, 35, 48, 57] 3 5 
(True, False) 
 
19. Determine o tipo das funções abaixo mostrando os passos até obter o 
resultado. Caso não seja possível determinar o tipo, explique o porquê. 
a) (.) map filter 
b) (.).map 
c) (.).(.) 
 
20. Para as funções g e h abaixo, verifique se elas estão corretas. Em caso 
afirmativo indique seu tipo. Caso contrário, explique qual o erro encontrado. 
 
a) g = map ff 
b) h = foldr ff 
 
Dados: 
ff :: (a -> [b]) -> Maybe a -> [b] 
ff f (Nothing) = [] 
ff f (Just x) = f x 
 
map :: (a -> b) -> [a] -> [b] 
foldr :: (a -> b -> b) -> b -> [a] -> b 
 
21. Para as expressões abaixo, indique se elas estão corretas. Em caso afirmativo 
indique seu tipo e seu resultado. 
 
 
a) map (even) (filter (>100) [10, 45, 300, 312, 561, 40, 28, 3]) 
b) snd (head (zip [1, 2, 3, 7] [True, True, False])) 
c) map (foldl1 (*)) [[0, 1], [1, 2, 4], [10]] 
 
22. Dada a expressão square (7 + 8), onde a função square está definida abaixo 
junto com as funções loop, nlist e dlist, há duas sequências de redução possíveis 
para esta expressão. 
 
square = \a -> a * a 
loop = \x -> x + loop x 
nlist = \n -> take n [n, 2*n..] 
dlist = \a -> \b -> map (\h -> div h (h-a)) [a..b] 
 
A primeira delas é a seguinte: 
 square (7 + 8) 
 = square 15 --definição do operador (+) 
 = 15 * 15 --definição da função square 
 = 225 --definição do operador (*) 
 
A segunda sequência de redução para a mesma expressão é: 
 square (7 + 8) 
 = (7 + 8) * (7 + 8) --definição da função square 
 = 15 * 15 --definição do operador (+) 
 = 225 --definição do operador (*) 
 
Estas duas sequências de reduções ilustram duas políticas de escolha de redução, 
conhecidas como innermost e outermost em grafos de redução, respectivamente. 
Na primeira delas, em cada passo de redução, foi escolhido o redex mais interno, ou 
seja, o redex que não continha qualquer outro redex interno a ele. Já na segunda 
sequência de reduções, optou-se pela escolha do redex mais externo, ou seja, um 
redex que não estava contido em qualquer outro. A redução outermost em grafos 
de redução é referenciada normalmente como lazy evaluation e a redução innermost 
como eager evaluation. 
 
Avalie as sub-expressões abaixo através das duas sequências de avaliação. Se não 
for possível realizar completamente a redução por alguma das sequências, 
justifique o porquê. 
 
a) snd (square 16, square 9) 
b) (+) 3 fst (12, loop 7) 
c) nlist (3+4) 
d) last (dlist 5 9) 
 
23. Dada a função f abaixo, a expressão f [1..] [2..] entra em loop? Justifique, 
explicando o porquê. 
 
f :: [Int] -> [Int] -> Int 
f (a:as) (b:bs) = a + b + head as + head bs 
 
24. Considere os seguintes tipos definidos em Haskell: 
 
data Termo = Constante Bool | Binaria Op Termo Termo | Unaria Op Termo 
data Op = E | OU | NEG 
 
Implemente uma função avaliadorLogico :: Termo -> Bool que avalie o Termo dado 
como parâmetro. 
 
Exemplo: 
Main> avaliadorLogico (Binaria OU (Unaria NEG (Constante True)) (Binaria OU 
(Constante False) (Constante True))) 
 
True 
 
25. Uma pilha é uma estrutura de dados em que todas as operações de inserção e 
remoção são realizadas pela mesma extremidade denominada topo. Geralmente, 
para manipular uma pilha, utilizam-se as operações push (insere um novo elemento 
no topo da pilha), pop (remove o elemento do topo da pilha) e top (acessa/retorna o 
elemento do topo da pilha). 
 
Crie os tipos algébricos polimórficos Pilha1 (utilizando apenas tipos recursivos) e 
Pilha2 (utilizando apenas listas) que podem ser exibidos. Implemente também as 
operações push1, pop1 e top1 que manipulam o tipo Pilha1 e push2, pop2 e top2 
que manipulam o tipo Pilha2. 
 
Caso a pilha esteja vazia e seja utilizada alguma das operações pop ou top, encerre 
a execução do programa e exiba a mensagem de erro: “Pilha vazia!”. 
 
26. Implemente um tipo algébrico polimórfico e recursivo Array que pode ser 
exibido. Um Array pode não conter nada ou conter um elemento de um tipo 
qualquer e outro Array do mesmo tipo. (O tipo algébrico Array não pode ser 
implementado por uma lista). 
 
Implemente também as funções: 
- alloc, que recebe um inteiro n e um elemento de um tipo qualquer s e retorna um 
Array de n posições todas com o valor s; 
- assign, que recebe um inteiro i, um elemento de um tipo qualquer s e um Array a e 
retorna o Array a com o valor do elemento da posição i substituído pelo valor do 
elemento s; 
- index, que recebe um inteiro i e um Array a e retorna o valor do elemento da 
posição i do Array a; 
- fromList, que recebe uma lista l de um tipo qualquer s e retorna um Array a do 
mesmo tipo contendo todos os elementos da lista l; 
- toList, que recebe um Array a de um tipo qualquer s e retorna uma lista l do 
mesmo tipo contendo todos os elementos do Array a. 
 
Para as funções assign e index, caso o índice do Array passado não contenha 
nenhum elemento, ou o tamanho do Array seja menor que o índice, deverá ser 
exibida uma mensagem de erro. 
 
27. Em Haskell, uma classe é uma coleção de tipos para os quais um conjunto de 
funções está definido. Por exemplo, os tipos que admitem comparação (se são 
iguais ou diferentes) entre os seus membros pertencem a classe Eq, os tipos que 
admitem uma ordenação de seus membros pertencem a classe Ord, etc. 
 
Para incorporar um novo tipo a uma classe, é necessário criar uma nova instância da 
classe e definir explicitamente cada função para os elementos do novo tipo. 
 
Compreendendo isso, crie uma instância da classe Funtor, mostrada abaixo, para o 
tipo algébrico Maybe t (já definido no arquivo “Prelude.hs”). Onde Funtor é uma 
classe que lida com tipos algébricos polimórficos de apenas um parâmetro. 
 
class Funtor d where 
 map' :: (t -> s) -> [d t] -> [d s] 
 filter' :: (t -> Bool) -> [d t] -> [d t] 
 foldl1' :: (t -> t -> t) -> [d t] -> d t 
 foldr1' :: (t -> t -> t) -> [d t] -> d t 
 (==>) :: (t -> d s) -> d t -> d s 
 (<==) :: d t -> (t -> d s) -> d s 
 
Exemplos: 
Main> map' (*10) [Just 1, Just 2, Just 3, Nothing, Just 10] 
[Just 10, Just 20, Just 30, Nothing, Just 100] 
 
Main> map' (<4) [Just 1, Just 2, Just 3, Nothing, Just 10] 
[Just True, Just True, Just True, Nothing, Just False] 
 
Main> filter' (<4) [Just 1, Just 2, Just 3, Nothing, Just 10] 
[Just 1, Just 2, Just 3] 
 
Main> foldl1' (^) [Just 2, Nothing, Just 2, Just 3] 
Just 64 
 
Main> foldr1' (^) [Just 2, Nothing, Just 2, Just 3] 
Just 256 
 
Main> foldr1' (*) (tail [Just 2]) 
Nothing 
 
Main> foldr1'(+) [Just 1] 
Just 1 
 
Main> foldl1' (+) [Just 1] 
Just 1 
Main> (\x -> Just(x^2+6)) ==> (Just 2) 
Just 10 
 
Main> Just “tenis” <== (\x -> Just (head x)) 
Just 't' 
 
 
28. Crie o tipo algébrico polimórfico Conj que pode ser exibido e que é 
representado por uma lista ordenada (de forma crescente) e sem repetições de 
elementos (semelhante a um conjunto de elementos). Crie, também, uma classe 
chamada OprConj que contenha as funções de união, diferença, interseção e 
diferença simétrica de conjuntos (ou seja, o conjunto dos elementos que pertencem 
a apenas um dos conjuntos). 
 
Em seguida, instancie o tipo Conj para a classe OprConj e implemente as funções 
dessa classe de forma que as de interseção e diferença simétrica utilizem 
necessariamente e apenas as funções de união e diferença. 
 
Os conjuntos resultantes de qualquer uma dessas operações devem sempre estar 
ordenados e não possuir elementos repetidos. Utilize alguma função de ordenação 
e/ou limite o tipo do conjunto às classes Eq e Ord, se necessário. 
 
29. Crie uma função que dado o nome de um arquivo e uma palavra imprime na 
tela o conteúdo das linhas do arquivo que essa palavra se encontra. 
 
30. Crie um programa que descobre o seu login a partir do seu nome e uma 
informação caso tenha número no login. O seu nome e a checagem de número deve 
ser passado pela entrada padrão (teclado) e a saída deve ser exibida no console. 
Após informar o seu nome, o programa deve perguntar se o seu login possui 
número, o número deve ser informado ou informe 0 caso não possua número. 
 
Exemplos: 
Main> main 
Informe seu nome completo: 
Alvaro Arthur Canto Sabino de Miranda Costa 
Caso tenha numero, informe (ou 0 caso nao tenha): 
0 
Seu login eh: aacsmc 
 
 
 
 
 
 
Main> main 
Informe seu nome completo: 
Gustavo de Oliveira Feitosa 
Caso tenha numero, informe (ou 0 caso nao tenha): 
0 
Seu login eh: gof 
 
Main> main 
Informe seu nome completo: 
Ihago Henrique Lucena e Silva 
Caso tenha numero, informe (ou 0 caso nao tenha): 
0 
Seu login eh: ihls 
 
Main> main 
Informe seu nome completo: 
Dino da Silva Sauro 
Caso tenha numero, informe (ou 0 caso nao tenha): 
3 
Seu login eh: dss3

Continue navegando