Recursos-LCC

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

View on GitHub
module 50Q where
import Data.List

-- 1

enumFromTo' :: Int -> Int -> [Int]
enumFromTo' start end 
    | start > end = []
    | otherwise = start:enumFromTo (start+1) end

enumFromToScary :: Int -> Int -> [Int]
enumFromToScary = curry (uncurry (flip takeWhile) . split (iterate (+1) . fst) ((>=) . snd))
    where split f g x = (f x, g x)

-- 2

enumFromThenTo' :: Int -> Int -> Int -> [Int]
enumFromThenTo' start next end
    | start > end && next - start > 0 || start < end && next - start < 0 = []
    | otherwise = start:enumFromThenTo' next (2 * next - start) end

-- 3

pp :: [a] -> [a] -> [a]
pp [] l = l
pp (h:t) l = h:pp t l

pp' :: [a] -> [a] -> [a]
pp' = flip $ foldr (:)

-- 4

getFromIndex :: [a] -> Int -> a
getFromIndex (h:t) n
    | n == 0 = h
    | otherwise = getFromIndex t (n - 1)

getFromIndex' :: [a] -> Int -> a
getFromIndex' l n = head (foldl (curry $ tail . fst) l [1..n])

-- 5

reverse' :: [a] -> [a]
reverse' [] = []
reverse' (h:t) = reverse' t ++ [h]

reverse_mini :: [a] -> [a]
reverse_mini = foldl (flip (:)) []

-- 6

take' :: Int -> [a] -> [a]
take' 0 _ = []
take' _ [] = []
take' n (h:t) 
    | n < 0 = []
    | otherwise = h : take' (n - 1) t

take_fold :: Int -> [a] -> [a]
take_fold n = foldl (\acc x -> if length acc < n then acc ++ [x] else acc) [] 

-- 7

drop' :: Int -> [a] -> [a]
drop' 0 l = l
drop' _ [] = []
drop' n (h:t)
    | n < 0 = h:t
    | otherwise = drop' (n - 1) t

drop_fold :: Int -> [a] -> [a]
drop_fold n l = foldr (\x acc -> if length acc < length l - n then x:acc else acc) [] l

-- 8

zip' :: [a] -> [b] -> [(a,b)]
zip' [] _ = []
zip' _ [] = []
zip' (h:t) (h':t') = (h,h'):zip' t t'

-- 9

elem' :: Eq a => a -> [a] -> Bool
elem' _ [] = False
elem' x (h:t) = x == h || elem' x t

elem_mini :: Eq a => a -> [a] -> Bool
elem_mini a = foldr ((||) . (==) a) False

elem'' :: Eq a => a -> [a] -> Bool
elem'' = any . (==)

-- 10

replicate' :: Int -> a -> [a]
replicate' 0 _ = []
replicate' n x
    | n < 0 = []
    | otherwise = x:replicate' (n - 1) x

replicate'' :: Int -> a -> [a]
replicate'' = flip $ flip take . repeat

-- 11

intersperse' :: a -> [a] -> [a]
intersperse' _ [] = []
intersperse' _ [h] = [h]
intersperse' x (h:t) = h:x:intersperse' x t 

-- 12

group' :: Eq a => [a] -> [[a]]
group' [] = []
group' (h:t) = (h:takeWhile (== h) t) : group' (dropWhile (== h) t)

group2_electric_boogaloo :: Eq a => [a] -> [[a]]
group2_electric_boogaloo [] = []
group2_electric_boogaloo l = takeWhile (== h) l : group2_electric_boogaloo (dropWhile (== h) l)
    where h = head l

group'' :: Eq a => [a] -> [[a]]
group'' [] = []
group'' (x:xs) = (x:aux xs):aux2 xs
    where aux (y:ys) = if y == x then y:aux ys else []
          aux [] = []
          aux2 [] = []
          aux2 (z:zs) = if z == x then aux2 zs else group'' (z:zs)

group''' :: Eq a => [a] -> [[a]]
group''' [] = []
group''' [x] = [[x]]
group''' (h:t)
    | h == head hr = (h : hr) : tr 
    | otherwise = [h] : hr : tr
    where (hr:tr) = group''' t

-- 13

concat' :: [[a]] -> [a]
concat' [] = []
concat' (h:t) = h ++ concat' t

concat'' :: [[a]] -> [a]
concat'' = foldr (++) []

-- 14

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

inits'' :: [a] -> [[a]]
inits'' [] = [[]]
inits'' [x] = [[],[x]]
inits'' (x:xs) = [] : aux x (inits'' xs)
    where aux a (h:t) = (a:h):aux a t
          aux _ [] = []

inits''' :: [a] -> [[a]]
inits''' = scanl (flip (flip (++) . return)) []

-- 15

tails' :: [a] -> [[a]]
tails' [] = [[]]
tails' l = l : tails' (tail l)

tails'' :: [a] -> [[a]]
tails'' = scanr (:) []

-- 16

isPrefixOf' :: Eq a => [a] -> [a] -> Bool
isPrefixOf' [] _ = True
isPrefixOf' _ [] = False
isPrefixOf' (h:t) (h':t') = h == h' && isPrefixOf' t t'

-- 17

isSuffixOf' :: Eq a => [a] -> [a] -> Bool
isSuffixOf' [] _ = True
isSuffixOf' _ [] = False
isSuffixOf' l l'@(_:t) = l == l' || isSuffixOf' l t

-- 18

isSubsequenceOf' :: Eq a => [a] -> [a] -> Bool
isSubsequenceOf' [] _ = True
isSubsequenceOf' _ [] = False
isSubsequenceOf' (h:t) (h':t') = h == h' && isSubsequenceOf' t t' || isSubsequenceOf' (h:t) t'

-- 19

elemIndices' :: Eq a => a -> [a] -> [Int]
elemIndices' _ [] = []
elemIndices' x (h:t)
    | x == h = 0 : map (+1) (elemIndices' x t)
    | otherwise = map (+1) (elemIndices' x t)

elemIndices'' :: Eq a => a -> [a] -> [Int]
elemIndices'' x l = [n | n <- [0..(length l - 1)], x == (l !! n)]

-- 20

nub' :: Eq a => [a] -> [a]
nub' [] = []
nub' (h:t) = h : filter (/= h) (nub' t)

nub2 :: Eq a => [a] -> [a]
nub2 [] = []
nub2 (h:t) = if h `elem` t then nub2 t else h:nub2 t

-- 21

delete' :: Eq a => a -> [a] -> [a]
delete' _ [] = []
delete' x (h:t)
    | x == h = t
    | otherwise = h:delete' x t

delete'' :: Eq a => a -> [a] -> [a]
delete'' = filter . (/=)

-- 22

remove :: Eq a => [a] -> [a] -> [a]
remove l [] = l
remove [] _ = []
remove l (h:t) = remove (delete' h l) t

-- 23

union' :: Eq a => [a] -> [a] -> [a]
union' l [] = l
union' l (h:t)
    | h `elem` l = union' l t
    | otherwise = union' (l ++ [h]) t

-- 24

intersect' :: Eq a => [a] -> [a] -> [a]
intersect' [] _ = []
intersect' (h:t) l
    | h `elem` l = h:intersect' t l
    | otherwise = intersect' t l

-- 25

insert' :: Ord a => a -> [a] -> [a]
insert' x [] = [x]
insert' x (h:t)
    | x > h = h:insert' x t
    | otherwise = x:h:t

-- 26

unwords' :: [String] -> String
unwords' [] = ""
unwords' (h:t) = h ++ (if null t then "" else " ") ++ unwords' t

-- 27

unlines' :: [String] -> String
unlines' [] = ""
unlines' (h:t) = h ++ "\n" ++ unlines' t

-- 28

pMaior :: Ord a => [a] -> Int
pMaior [_] = 0 -- [_] é uma lista com apenas um elemento, o underscore apenas substitui o nome de uma variável
pMaior (h:t)
    | h > (t !! x) = 0
    | otherwise = 1 + x
    where x = pMaior t

-- OU (a segunda versão usa uma função auxiliar, mas é mais intuitiva)

pMaior' :: Ord a => [a] -> Int
pMaior' (h:t) = aux 0 0 h t
    where aux _ nm _ [] = nm
          aux n nm x (l:ls) = if l > x -- n é o índice "atual", nm é o índice do valor máximo da lista
                              then aux (n + 1) (n + 1) l ls 
                              else aux (n + 1) nm x ls

-- 29

temRepetidos ::  Eq a => [a] -> Bool
temRepetidos [] = False
temRepetidos (h:t) = h `elem` t || temRepetidos t

-- 30

algarismos :: [Char] -> [Char]
algarismos [] = []
algarismos (h:t)
    | h `elem` ['0'..'9'] = h:algarismos t
    | otherwise = algarismos t

algarismos' :: [Char] -> [Char]
algarismos' = filter (`elem` ['0'..'9'])

-- 31

posImpares :: [a] -> [a]
posImpares [] = []
posImpares [_] = []
posImpares (h:s:t) = s:posImpares t

posImpares' :: [a] -> [a]
posImpares' = map snd . filter (odd . fst) . zip (iterate (+1) 0)

-- 32

posPares :: [a] -> [a]
posPares [] = []
posPares [x] = [x]
posPares (h:s:t) = h:posPares t

posPares' :: [a] -> [a]
posPares' = map snd . filter (even . fst) . zip [0..]

-- 33

isSorted :: Ord a => [a] -> Bool
isSorted [] = True
isSorted [_] = True
isSorted (h:s:t) = s >= h && isSorted (s:t)

-- 34

-- Função insert' definida na questão 25

iSort :: Ord a => [a] -> [a]
iSort [] = []
iSort (h:t) = insert h (iSort t)

-- Outras formas de ordenar listas:

quickSort :: Ord a => [a] -> [a]
quickSort [] = []
quickSort (l:ls) = maisPequenos ++ [l] ++ maiores
    where maisPequenos = quickSort $ filter (<=l) ls
          maiores = quickSort $ filter (>l) ls

mergeSort :: Ord a => [a] -> [a]
mergeSort [] = []
mergeSort [x] = [x]
mergeSort l = merge (mergeSort metade1) (mergeSort metade2)
    where (metade1,metade2) = splitAt (div (length l) 2) l
          merge :: Ord a => [a] -> [a] -> [a]
          merge [] l = l
          merge l [] = l
          merge (a:b) (c:d) = if a < c then a:merge b (c:d) else c:merge (a:b) d

-- 35

menor :: String -> String -> Bool
menor _ "" = False
menor "" _ = True
menor (h:t) (h':t') = h < h' || menor t t'


-- 36

elemMSet ::  Eq a => a -> [(a,Int)] -> Bool
elemMSet _ [] = False
elemMSet a ((x,_):xs) = a == x || elemMSet a xs

elemMSet' :: Eq a => a -> [(a,Int)] -> Bool
elemMSet' = any . (. fst) . (==)

-- 37

lengthMSet ::  [(a,Int)] -> Int
lengthMSet [] = 0
lengthMSet ((x,n):xs) = n + lengthMSet xs

lengthMSet' :: [(a,Int)] -> Int
lengthMSet' = sum . map snd

-- 38

converteMSet :: [(a,Int)] -> [a]
converteMSet [] = []
converteMSet ((x,1):xs) = x:converteMSet xs
converteMSet ((x,n):xs) = x:converteMSet ((x,n-1):xs)

-- OU

converteMSet' :: [(a,Int)] -> [a]
converteMSet' [] = []
converteMSet' ((x,n):xs) = replicate n x ++ converteMSet xs

-- 39

insereMSet :: Eq a => a -> [(a,Int)] -> [(a,Int)]
insereMSet x [] = [(x,1)]
insereMSet x ((a,n):xs) = if x == a then (a,n+1):xs else (a,n):insereMSet x xs

-- 40

removeMSet :: Eq a => a -> [(a,Int)] -> [(a,Int)]
removeMSet x [] = []
removeMSet x ((a,n):xs) = if x == a then xs else (a,n):removeMSet x xs

-- 41

constroiMSet :: Ord a => [a] -> [(a,Int)]
constroiMSet [] = []
constroiMSet (l:ls) = insereMSet l (constroiMSet ls)

-- OU

constroiMSet' :: Ord a => [a] -> [(a,Int)]
constroiMSet' [] = []
constroiMSet' (l:ls) = (l,1 + length (filter (==l) ls)):constroiMSet' (filter (/=l) ls)

-- 42

partitionEithers ::  [Either a b] -> ([a],[b])
partitionEithers l = (partitionLefts l, partitionRights l)
    where partitionLefts [] = []
          partitionLefts ((Left x):ls) = x:partitionLefts ls
          partitionLefts ((Right _):ls) = partitionLefts ls
          partitionRights [] = []
          partitionRights ((Left _):ls) = partitionRights ls
          partitionRights ((Right x):ls) = x:partitionRights ls

partitionEithers' :: [Either a b] -> ([a],[b])
partitionEithers' [] = ([],[])
partitionEithers' ((Left a):t) = (a:as,bs)
    where (as,bs) = partitionEithers' t
partitionEithers' ((Right b):t) = (as,b:bs)
    where (as,bs) = partitionEithers' t  

-- 43

catMaybes :: [Maybe a] -> [a]
catMaybes [] = []
catMaybes (m:ms) = case m of Nothing -> catMaybes ms
                             Just x -> x:catMaybes ms

catMaybes' :: [Maybe a] -> [a]
catMaybes' [] = []
catMaybes' ((Just a):ms) = a:catMaybes' ms
catMaybes' (Nothing:ms) = catMaybes' ms

-- 44

data Movimento = Norte | Sul | Este | Oeste deriving Show

posicao :: (Int,Int) -> [Movimento] -> (Int,Int)
posicao p [] = p
posicao (x, y) (m:ms) = posicao (case m of Norte -> (x, y + 1)
                                           Sul -> (x, y - 1)
                                           Este -> (x + 1, y)
                                           Oeste -> (x - 1, y)) ms

-- 45

caminho :: (Int, Int) -> (Int, Int) -> [Movimento]
caminho (xi, yi) (xf, yf) | xi < xf   = Este : caminho (xi + 1, yi) (xf, yf)
                          | xi > xf   = Oeste : caminho (xi - 1, yi) (xf, yf)
                          | yi < yf   = Norte : caminho (xi, yi + 1) (xf, yf)
                          | yi > yf   = Sul : caminho (xi, yi - 1) (xf, yf)
                          | otherwise = []

-- 46

vertical :: [Movimento] -> Bool
vertical [] = True
vertical (l:ls) = case l of Este -> False
                            Oeste -> False
                            _ -> vertical ls

-- 47

data Posicao = Pos Int Int deriving Show

maisCentral ::  [Posicao] -> Posicao
maisCentral = foldl1 (\(Pos xacc yacc) (Pos x y) -> if (xacc^2 + yacc^2) > (x^2 + y^2) then Pos x y else Pos xacc yacc)

maisCentral' :: [Posicao] -> Posicao
maisCentral' [Pos x y] = Pos x y
maisCentral' ((Pos x y):(Pos a b):ps) = if (x^2 + y^2) < (a^2 + b^2) then maisCentral (Pos x y : ps) else maisCentral (Pos a b : ps)

-- 48

vizinhos ::  Posicao -> [Posicao] -> [Posicao]
vizinhos (Pos x y) = filter (\(Pos a b) -> abs (a - x) + abs (b - y) == 1)

vizinhos' :: Posicao -> [Posicao] -> [Posicao]
vizinhos' _ [] = []
vizinhos' (Pos x y) ((Pos xv yv):ps) = if abs (x - xv) == 1 && y == yv || abs (y - yv) == 1 && x == xv 
                                       then Pos xv yv : vizinhos' (Pos x y) ps 
                                       else vizinhos' (Pos x y) ps

-- 49

mesmaOrdenada :: [Posicao] -> Bool
mesmaOrdenada [] = True
mesmaOrdenada [Pos _ _] = True
mesmaOrdenada ((Pos _ y):(Pos x2 y2):ps) = y == y2 && mesmaOrdenada (Pos x2 y2 : ps)

mesmaOrdenada' :: [Posicao] -> Bool
mesmaOrdenada' [] = True
mesmaOrdenada' (Pos _ y:t) = all ((==) y . (\(Pos _ yy) -> yy)) t 

-- 50

data Semaforo = Verde | Amarelo | Vermelho deriving Show

interseccaoOK :: [Semaforo] -> Bool
interseccaoOK ss = length [s | s <- ss, case s of Vermelho -> False; _ -> True] < 2