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