Programação Funcional

50 Questões Fichas Testes/Exames

Exame 2020-01-25

Voltar

1. Apresente uma definição recursiva das seguintes funções (pré-definidas) sobre listas:

a) inits:: [a] -> [[a]] que calcula a lista dos prefixos de uma lista. Por exemplo, inits [11,21,13] corresponde a [[],[11],[11,21],[11,21,13]].

inits :: [a] -> [[a]]
inits [] = [[]]
inits l = inits (init l) ++ [l]

b) isPrefix0f:: Eq a => [a] -> [a] -> Bool que testa se uma lista é prefixo de outra. Por exemplo, isPrefix0f [10,20] [10,20,30] corresponde a True enquanto que isPrefix0f [10,30] [10,20,30] corresponde a False.

isPrefixOf :: Eq a => [a] -> [a] -> Bool
isPrefixOf [] _ = True
isPrefixOf _ [] = False
isPrefixOf (x:xs) (y:ys) = x == y && isPrefixOf xs ys

2. Considere o seguinte tipo para representar árvores binárias.

data BTree a = Empty
             | Node a (BTree a) (BTree a)
    deriving Show

a) Defina a função folhas :: BTree a -> Int que calcula o número de folhas (i.e., nodos sem descendentes) da árvore.

folhas :: BTree a -> Int
folhas Empty = 0
folhas (Node _ Empty Empty) = 1
folhas (Node _ l r) = folhas l + folhas r

b) Defina a função path :: [Bool] -> BTree a -> [a] que, dado um caminho (False corresponde a esquerda e True a direita) e uma árvore, dá a lista com a informação dos nodos por onde esse caminho passa.

path :: [Bool] -> BTree a -> [a]
path _ Empty = []
path [] (Node e _ _) = [e]
path (h:t) (Node e l r) = e : path t (if h then r else l)  

3. Uma representação possível de polimómios é pela sequência dos coeficientes - têm que se armazenar também os coeficientes nulos pois será a posição do coeficiente na lista que dará o grau do monómio.

type Polinomio = [Coeficiente]
type Coeficiente = Float

A representação do polinómio 2x^5 - 5x^3 será então [0,0,0,-5,0,2], que corresponde ao polinómio 0x^0 + 0x^1 + 0x^2 - 5x^3 + 0x^4 + 2x^5. Nas questões que se seguem, use, sempre que possível, funções de ordem superior.

a) Defina a operação valor :: Polinomio -> Float -> Float que calcula o valor do polinómio para um dado x.

valor :: Polinomio -> Float -> Float
valor p x = foldr (\(g,c) acc -> acc + c * x ^ g) 0 $ zip [0..] p

b) Defina a operação deriv :: Polinomio -> Polinomio que calcula a derivada de um polinómio.

deriv :: Polinomio -> Polinomio
deriv = map (uncurry (*)) . tail . zip [0..]

c) Defina a operação soma :: Polinomio -> Polinomio -> Polinomio de adição de polinómios.

soma :: Polinomio -> Polinomio -> Polinomio
soma p1 p2 = zipWith (+) (pad p1) (pad p2)
    where max_len = max (length p1) (length p2)
          pad p = p ++ replicate (max_len - length p) 0

4. Considere a seguinte definição para representar matrizes: type Mat a = [[a]]. ex = [[1,4,3,2,5], [6,7,8,9,0], [3,5,4,9,1]] representa a matriz abaixo desenhada.

| 1 4 3 2 5 |
| 6 7 8 9 0 |
| 3 5 4 9 1 |

a) Defina a função quebraLinha :: [Int] -> [a] -> [[a]] que recebe uma lista de inteiros s e uma linha l, e produz a lista de segmentos contíguos de l de comprimento indicado em s. Por exemplo, quebraLinha [2,3] [1,4,3,2,5] == [[1,4],[3,2,5]].

quebraLinha :: [Int] -> [a] -> [[a]] 
quebraLinha [] _ = []
quebraLinha (x:xs) l = take x l : quebraLinha xs (drop x l)

b) Defina a função fragmenta :: [Int] -> [Int] -> Mat a -> [Mat a] que recebe duas lista de inteiros (com a partição das linhas e das colunas) e uma matriz, e produz a lista de (sub)-matrizes de acordo com essa partição. Por exemplo,fragmenta [2,1] [2,3] ex == [ [[1,4],[6,7]], [[3,2,5],[8,9,0]], [[3,5]], [[4,9,1]] ].

fragmenta :: [Int] -> [Int] -> Mat a -> [Mat a]
fragmenta [] _ _ = []
fragmenta (x:xs) c m = fragmentaCols c (take x m) ++ fragmenta xs c (drop x m)

fragmentaCols :: [Int] -> Mat a -> [Mat a]
fragmentaCols [] _ = []
fragmentaCols (x:xs) m = map (take x) m : fragmentaCols xs (map (drop x) m)

c) Defina a função geraMat :: (Int,Int) -> (Int,Int) -> IO (Mat Int) tal que geraMat (x,y) (a,b) gera aleatoriamente uma matriz com x linhas e y colunas, cujos valores estão compreendidos entre a e b. Sugestão: use a função randomRIO :: Random a => (a,a) -> IO a.

geraMat :: (Int,Int) -> (Int,Int) -> IO (Mat Int)
geraMat (x,y) (a,b) = 
    sequence 
    $ replicate y 
    $ sequence 
    $ replicate x 
    $ randomRIO (a,b)