-- Primeira Prova de LP2 -- 10/12/98 ------------------------------------ {- 1 - (2.0) Compreensoes de listas sao um excelente mecanismo para definir listas a partir de outras listas. Usando compreensao de listas, defina as seguintes funcoes: -} -- map :: (a->b) -> [a] -> [b] -- filter :: (a -> Bool) -> [a] -> [a] mcs :: Int -> Int -> [Int] -- multiplos comuns de dois numeros (ate' no maximo x * y) mcs x y = [ z | z <- [(min x y)..(x*y)], mod z x == 0, mod z y == 0] dcs :: Int -> Int -> [Int] dcs x y = [ z | z<- [1..(max x y)], mod x z == 0, mod y z == 0] -- divisores comuns de dois numeros {- 2 - Algumas calculadoras, para evitar o uso de parenteses, trabalham com uma notacao matematica onde as operacoes aparecem apos os operandos, por exemplo: "3 4 +" --> "3 + 4" --> 7 "3 4 + 11 1 - *" --> "(3 + 4) * (11 - 1)" --> 70 "3 4 11 1 - * *" --> "3 * (4 * (11 - 1))" --> 120 "3 4 11 1 - 5 * * +" --> "3 + (4 * ((11 - 1) * 5))" --> 203 faca funcoes para: (1.0) separar uma String em Strings apenas com numeros ou operacoes: -} separa :: String -> [String] separa [] = [] separa str = showaux str : separa (resto str) showaux :: String -> String showaux [] = [] showaux (a:as) | a == ' ' = [] | otherwise = a : showaux as resto :: String -> String resto [] = [] resto (a:as) | a == ' ' = as | otherwise = resto as {- (0.5) contar o numero de operacoes em uma String nesta notacao -} ops :: String -> Int ops [] = 0 ops (a:as) | (operador a) == [] = ops as | otherwise = 1 + ops as operador :: Char -> String operador c = [ ch | ch <- "*-+/", c == ch ] {- (1.0) contar o numero de operandos em uma String nesta notacao -} operandos :: String -> Int operandos [] = 0 operandos str = length [ st | st <- (separa str), not (compString st "*-+/") ] compString :: String -> String -> Bool compString [] [] = True compString s1 [] = False compString [] s2 = True compString (a:as) (b:bs) | a == b = compString as bs | otherwise = compString (a:as) bs -- (1.0) converter um operando em seu respectivo inteiro: stoi :: String -> Int stoi (a:as) | a == '-' = (-1)*(stoi as) | (length (a:as)) == 2 = (stoi [a])*10 + (stoi as) | (length (a:as)) == 3 = (stoi [a])*100 + (stoi as) | otherwise = (numb a "0123456789") numb :: Char -> String -> Int numb c (a:as) | c == a = 0 | otherwise = 1 + numb c as -- (1.0) qual o tipo da seguinte funcao: stoop :: String -> Int -> Int -> Int stoop "*" = (*) stoop "+" = (+) stoop "-" = (-) stoop "/" = div -- (2.0) avaliar uma expressao nesta notacao "3 4 + 11 1 - *" evalR :: String -> Int evalR str | length (separa str) == 3 = auxilia (separa str) | otherwise = evalR (auxilia2 (separa str)) auxilia :: [String] -> Int auxilia [a,b,op] = (stoop op (stoi a) (stoi b)) auxilia2 :: [String] -> String auxilia2 [] = [] auxilia2 [op] = op auxilia2 [a,b] = a ++ " " ++ b auxilia2 [a,b,op] = a ++ " " ++ b ++ " " ++ op auxilia2 (a:b:op:as) | ops a /= 0 = a ++ " " ++ auxilia2 (b:op:as) | ops b /= 0 = a ++ " " ++ b ++ " " ++ auxilia2 (op:as) | otherwise = show (stoop op (stoi a) (stoi b)) ++ " " ++ auxilia2 as -- (2.0) mostrar uma expressao nesta notacao com parenteses "3 4 + 11 1 - *" = "(3 + 4) * (11 - 1)" showparen :: String -> String showparen str = showparen2 (separa str) showparen2 :: [String] -> String showparen2 str | length str == 3 = aux str | otherwise = showparen2 (aux2 str) aux :: [String] -> String aux [a,b,op] = a ++ " " ++ op ++ " " ++ b aux2 :: [String] -> [String] aux2 [] = [] aux2 [op] = [op] aux2 [a,b] = [a,b] aux2 [a,b,op] = [a,b,op] aux2 (a:b:op:as) | ops a /= 0 && length (a) == 1 = a : aux2 (b:op:as) | ops b /= 0 && length (b) == 1 = a : b : aux2 (op:as) | otherwise = ("(" ++ a ++ " " ++ op ++ " " ++ b ++ ")") : aux2 as