Aula 5
livro texto (cap 8 Algebraic data types intro e Recursive data structures apenas)
1 Teste
escreva a funçao splitseq
que dado uma subsequencia pequena (o separador) e uma
sequencia (grande), usa o separador para quebrar a
sequencia grande em techos.
splitseq "abc" "123abc456abc890" ==> ["123","456","890"]
escreva o tipo de splitseq
(1 ponto)
se a funçao so faz o primeiro split (splitseq "abc" "123abc456abc890" ==> ["123","456abc890"]) o exercicio vale 2.5
se a funçao faz todos os splits, vale 3.0
No split da liçao de casa vc tinha algo como:
splitall t (x:xs) | x == t = faz also com o xs
o central desse problema (uma vez que vc ja implementou o splitall) é
que o teste se o separador é igual ao comeco da lista era simples no
caso de um unico separador (quebra a lista no 1 elemento e testa se
ele é igual ao separador) e se for, o que sobra da lista sem o
separador também é simples (o xs
).
no caso onde o separador é uma sequencia o teste se o separador é igual ao comeco, e computar o que sobra da lista sem o separador precisam ser re-escritos
1.1 solucao
Primeiro o splitall
splitall :: (Eq a) => a -> [a] -> [[a]] splitall sep [] = [[]] splitall sep (x:xs) | x==sep = []:(a:as) | otherwise = (x:a):as where (a:as) = splitall sep xs
primeira versao - usando o take
e drop
splitseq :: (Eq a) => [a] -> [a] -> [[a]] splitseq sep lista = splitseq' sep lista n where n = length sep splitseq' sep [] _ = [[]] splitseq' sep l n | sep == inicio = []:(a:as) | otherwise = (x:b):bs where inicio = take n l x = head l resto = drop n l (a:as) = splitseq' seq resto n (b:bs) = splitseq' seq (tail l) n
Note que parece que nos estamos fazendo duas chamadas para o
splitseq
no where
que tornaria o codigo exponencial. Mas lembre-se
do lazy evaluation do haskell. Ambas chamadas de splitseq
são thunks
e não rodam até que sejam necessárias. Portanto do ponto de vista
prático é como se só a versão do splitseq
que é necessaria é
executada.
Segunda versao, usando funcoes para testar o comeco e o resto
splitseq :: (Eq a) => [a] -> [a] -> [[a]] splitseq sep [] = [[]] splitseq sep l | comeco sep l = []:(splitseq sep (resto sep l)) | otherwise = ((head l):a):as where (a:as) = splitseq sep (tail l) comeco [] _ = True comeco _ [] = False comeco (a:as) (b:bs) = a==b && (comeco as bs) resto [] x = x resto (_:as) (_,bs) = resto as bs
Terceira versao fazendo o comeco e resto numa so funcao
splitseq :: (Eq a) => [a] -> [a] -> [[a]] splitseq sep [] = [[]] splitseq sep l | com = []:(splitseq sep res) | otherwise = ((head l):a):as where (com,res) = aux sep l (a:as) = splitseq sep (tail l) aux [] res = (True, res) aux _ [] = (False, []) aux (a:as) (b:bs) | a==b = aux as bs | otherwise = (False,[])
2 Criando seus proprios tipos
data
data Ponto = Ponto Float Float -- x e y de um ponto data Figura = Circulo Ponto Float | Retangulo Ponto Ponto area (Circulo _ r) = 2 * 3.14 * r area (Retangulo (Ponto xa ya) (Ponto xb yb)) = abs ((ya-yb)*(xa-xb))
data Ponto = Ponto Float Float deriving (Eq,Read,Show)
Definicao de tipos pode conter variaveis de tipo
data Tree a = Vazia | No a (Tree a) (Tree a) deriving (Eq,Show,Read)
Isso define uma arvore binária de a
seja o que for a
3 Exercicios
- acha um item buma arvore de busca binaria
- verifica se uma arvore é um abb
data Tree a = Vazia | No a (Tree a) (Tree a) deriving (Eq,Show,Read) abb Vazia = True abb (No _ Vazia Vazia) = True abb (No x Vazia ad) = (abb ad) && (x < (menor ad)) abb (No x ae Vazia) = (abb ae) && (x > (maior ae)) abb (No x ae ad) = (abb ae) && (abb ad) && (x < (menor ad)) && (x>(maior ae)) maior (No x _ Vazia) = x maior (No x _ ad) = maior ad menor (No x Vazia _) = x menor (No x ae _) = menor ae
versao 2 - computa o maior e o menor ao mesmo tempo
abb a = fst (abb'a) abb' Vazia = (True,0,0) abb' (No x Vazia Vazia) = (True,x,x) abb' (No x ae Vazia) = (bae && (x > mae), mea,x) where (bae,mee,mae) = abb' ae abb'(No x Vazia ad) = (bae && (x < med), x, mad) where (bad,med,mad) = abb' ad abb' (No x ae ad) = (bae && bad && (x > mae) && (x < med), mee, mad) where (bae,mee,mae) = abb' ae (bad,med,mad) = abb' ad
- insere um item numa abb
- remove um item de uma abb
- calcula a profundidade maxima de uma abb
- coverte uma abb numa lista em ordem infixa (arvore-esquerda, no, arvore-direita)
- converte uma abb numa lista em ordem prefixa (no, ae, ad)
- converte uma lista em uma abb