Aula 5

livro texto (cap 8 Algebraic data types intro e Recursive data structures apenas)

Haskell online

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

Author: Jacques Wainer

Created: 2018-08-28 Tue 14:48

Validate