Recursos-LCC

Um arquivo de todo material que consegui reunir, pertinente ao curso de LCC da UM.

View on GitHub
module Ficha01 where
import Data.Char
-- Exercício 1

perimetro' :: Double -> Double
perimetro' r = 2 * pi * r

dist' :: (Num a, Eq a, Floating a) => (a,a) -> (a,a) -> a
dist' (x1, y1) (x2, y2) = sqrt(dx ^ 2 + dy ^ 2) where dx = x1 - x2; dy = y1 - y2
                        
primUlt :: [a] -> (a, a)
primUlt l = (head l, last l)

multiplo :: Int -> Int -> Bool
multiplo x y = mod x y == 0

multiplo' :: Int -> Int -> Bool
multiplo' x = (==) 0 . mod x

multiplo'' :: Int -> Int -> Bool
multiplo'' = curry ((== 0) . uncurry mod)

truncaImpar l = if even $ length l then l else tail l 

max2 :: Ord p => p -> p -> p
max2 x y = if x > y then x else y

max3 :: Ord p => p -> p -> p -> p
max3 x y = max2 (max2 x y)

-- Exercício 2

nRaizes a b c 
    | delta > 0 = 2 
    | delta == 0 = 1
    | delta < 0 = 0 
    where delta = b^2 - 4*a*c

raizes a b c 
    | n == 2 = [x1, x2] 
    | n == 1 = [x1] 
    | n == 0 = [] 
    where n = nRaizes a b c
          delta = b^2 - 4*a*c
          (x1,x2) = (((-b) + sqrt delta)/ (2*a), ((-b) - sqrt delta)/ (2*a))

-- Exercício 3

-- type Hora = (Int, Int)

-- horaValida :: Hora -> Bool

horaValida (h, m) = elem h [0..23] && elem m [0..59]

horaMaior (h1, m1) (h2, m2) = if horaValida (h1, m1) && horaValida (h2, m2)
                                  then if h1 > h2 || (h1 == h2 && m1 > m2)
                                           then (h1, m1) 
                                           else (h2, m2) 
                                  else error "Hora inválida!"

-- Versão mais pequena da função acima:
horaMaiorv2 h1 h2 = if h1 > h2 then h1 else h2

hor2min (h, m) = 60 * h + m
min2hor min = (div min 60, mod min 60)

hordiff h1 h2 = min2hor (abs (hor2min h1 - hor2min h2))

addmins (h, m) min = min2hor (mod (hor2min (h, m) + min) 1440)

-- Exercício 4

data Hora = H Int Int deriving (Show, Eq)

horaValida' :: Hora -> Bool
horaValida' (H h m) = elem h [0..23] && elem m [0..59]

(H h m) `horaDepois` (H h2 m2) = (h,m) >= (h2,m2)

hor2min' (H h m) = 60 * h + m

min2hor' min = H (div min 60) (mod min 60)

hordiff' h1 h2 = min2hor' $ abs $ hor2min' h1 - hor2min' h2

addmins' hor min = min2hor' $ mod (hor2min' hor + min) 1440

-- Exercício 5

data Semaforo = Verde | Amarelo | Vermelho deriving (Show, Eq)

next :: Semaforo -> Semaforo
next s = case s of Verde -> Amarelo
                   Amarelo -> Vermelho
                   Vermelho -> Verde

stop :: Semaforo -> Bool
stop s
    | s == Vermelho = True
    | otherwise = False

safe :: Semaforo -> Semaforo -> Bool
safe s1 s2 = s1 == Vermelho || s2 == Vermelho

-- Exercício 6

data Ponto = Cartesiano Double Double | Polar {distPonto :: Double, anguloPonto :: Double} deriving (Show,Eq)

posx :: Ponto -> Double
posx ponto = case ponto of Cartesiano x _ -> x
                           Polar d a -> if a == pi/2 then 0 else d * cos a

posy :: Ponto -> Double
posy ponto = case ponto of Cartesiano _ y -> y
                           Polar d a -> if a == pi then 0 else d * sin a

raio :: Ponto -> Double
raio ponto = case ponto of Cartesiano x y -> sqrt $ x^2 + y^2
                           Polar d _ -> d

angulo :: Ponto -> Double
angulo ponto = case ponto of Cartesiano x y -> if x < 0 && y == 0 then pi else
                                               if x < 0 then pi + atan (y/x) else
                                               atan (y/x)
                             Polar _ a -> a

dist :: Ponto -> Ponto -> Double
dist ponto1 ponto2 = sqrt (((posx ponto1 - posx ponto2) ^ 2) + (posy ponto1 - posy ponto2) ^ 2)

-- Exercício 7

data Figura = Circulo Ponto Double | Retangulo Ponto Ponto | Triangulo Ponto Ponto Ponto deriving (Show, Eq)

poligono :: Figura -> Bool
poligono (Circulo c r) = False
poligono (Retangulo p1 p2) = posx p1 /= posx p2 && posy p1 /= posy p2 -- Verifica que os pontos não têm o mesmo valor de x ou y
poligono (Triangulo p1 p2 p3) = (posy p2 - posy p1) / (posx p2 - posx p1) /= (posy p3 - posy p2) / (posx p3 - posx p2) -- Verifica que os pontos não pertencem todos à mesma reta

vertices :: Figura -> [Ponto]
vertices (Circulo _ _) = []
vertices retang@(Retangulo p1 p2) = if poligono retang then [p1, Cartesiano (posx p1) (posy p2), Cartesiano (posx p2) (posy p1), p2] else []
vertices triang@(Triangulo p1 p2 p3) = if poligono triang then [p1, p2, p3] else []

area :: Figura -> Double
area (Triangulo p1 p2 p3) =
    let a = dist p1 p2
        b = dist p2 p3
        c = dist p3 p1
        s = (a+b+c) / 2 -- semi-perimetro
    in sqrt (s*(s-a)*(s-b)*(s-c)) -- fórmula de Heron
area (Circulo _ r) = pi * (r ^ 2)
area (Retangulo p1 p2) = abs (posx p2 - posx p1) * abs (posy p2 - posy p1) 

perimetro :: Figura -> Double
perimetro (Circulo _ r) = 2 * pi * r
perimetro (Retangulo p1 p2) = 2 * abs (posx p2 - posx p1) + 2 * abs (posy p2 - posy p1)
perimetro (Triangulo p1 p2 p3) = dist p1 p2 + dist p2 p3 + dist p1 p3

-- Exercicio 8

isLower' :: Char -> Bool
isLower' ch = ch `elem` ['a'..'z']

isUpper' :: Char -> Bool
isUpper' ch = ch `elem` ['A'..'Z']

isDigit' :: Char -> Bool
isDigit' d = d `elem` ['0'..'9']

isAlpha' :: Char -> Bool
isAlpha' ch = isLower' ch || isUpper' ch

toUpper' :: Char -> Char
toUpper' ch = if isLower' ch then chr (ord ch - 32) else ch

intToDigit' :: Int -> Char
intToDigit' n = chr (n + 48)

digitToInt' :: Char -> Int 
digitToInt' ch = ord ch - 48