Buscar

Questões de Haskell Resolvidas

Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original

Haskell/where.hs
quad :: Int -> Int
quad n = quad_n
			where 
				quad_n = n*n
Haskell/whatfiles.sh
#!/bin/bash
if [ "$#" -eq 3 ]; then
	files=`ls -R $1`
else
	files=`ls $1`
fi
for f in $files
do
	cat $f | grep "$2" >& /dev/null
	if [ "$?" -eq 0 ]; then
		echo $f
	fi
done
Haskell/vasos.hs
{-0 0
encher2 x -> y
x 4
0 4
completar1 x -> y
(x + min(y, 3-x)) (y - min(y,3-x))
3 1
esvaziar1 x -> y
0 y
0 1
completar1 x -> y
(x + min(y, 3-x)) (y - min(y, 3-x))
1 0
------------------------------------------------------
0 0
encher1
3 0
completar2
0 3
encher 1
3 3
completar 2
2 4-}
--x possui capacidade 3
--y possui capacidade 4
--inicialmente x e y devem estar vazios ou seja, deve-ser chamar resolver (0,0)
my_min :: (Int, Int) -> Int
my_min (x,y) | (x < y) = x
			 | otherwise = y
encher1 :: (Int, Int) -> (Int, Int)
encher1 (x,y) = (3,y)
completar2 :: (Int, Int) -> (Int, Int)
completar2 (x,y) = ( (x - my_min(x,(4-y))),(y + my_min(x,(4-y))) )
resolver :: (Int, Int) ->[(String, (Int,Int))]
resolver (x,y) = [("Encher 1", (encher1(x,y))), ("Completar 2 com 1", completar2(encher1(x,y))), ("Encher 1",encher1(completar2(encher1(x,y)))), ("Completar 2 com 1",completar2(encher1(completar2(encher1(x,y)))))]
Haskell/resultadoAprovacoes.hs
type Nota = Float
type Falta = Integer
type Status = String
type Nome = String
data Registro = Aluno Nome Nota Nota Nota Nota Falta 
				deriving(Show)
carga_horaria :: Float
-- Por padrao foi considerada uma carga horaria de 40 horas
carga_horaria = 40.0
-- Status possíveis:
rf :: Status
rf = "Reprovado por faltas"
rn :: Status
rn = "Reprovado por notas"
am :: Status
am = "Aprovado por media"
ef :: Status
ef = "Exame final"
-- Retorna media das tres notas
md :: Nota -> Nota -> Nota -> Nota
md x y z = ((x+y+z)/3.0)
menorAluno :: Registro -> Registro -> Bool
menorAluno (Aluno x _ _ _ _ _) (Aluno y _ _ _ _ _) | x < y = True
												 | otherwise = False
-- Ordena uma lista de alunos pelo nome
-- Exemplo: [(Aluno "Milton" 10.0 10.0 10.0 0.0 33), (Aluno "Astrobaldo" 3.0 5.0 1.0 5.0 33)]
-- --> [Aluno "Astrobaldo" 3.0 5.0 1.0 5.0 33,Aluno "Milton" 10.0 10.0 10.0 0.0 33]
menores :: Registro -> [Registro] -> [Registro]
menores n [] = []
menores n x = [b | b <- x, menorAluno b n]
maiores :: Registro -> [Registro] -> [Registro]
maiores n [] = []
maiores n x = [b | b <- x, menorAluno n b]
ordenarAluno :: [Registro] -> [Registro]
ordenarAluno [] = []
ordenarAluno (x:[]) = [x]
ordenarAluno (x:xs) = (ordenarAluno (menores x xs)) ++ [x] ++ (ordenarAluno (maiores x xs))
-- Mostra qual foi a nota final e o resultado para um determinado aluno
-- Exemplo: resultado (Aluno "Milton" 10.0 10.0 10.0 0.0 33) --> ("Aprovado por media",10.0)
-- 			resultado (Aluno "Astrobaldo" 3.0 5.0 1.0 5.0 33) --> ("Reprovado por notas",4.0)
-- resultado (Aluno "Irresponsável" 3.0 2.0 1.0 0.0 5) --> ("Reprovado por faltas",0.0)
resultado :: Registro -> (Status, Nota)
resultado (Aluno _ x y z w f) | (fromIntegral(f)/carga_horaria) < 0.75 = (rf, 0.0)
						 | ((md x y z) >= 7.0) = (am, (md x y z))
						 |	(((md x y z) + w)/2.0 < 6.0) = (rn, (((md x y z) + w)/2.0))
						 | otherwise = (ef, (((md x y z) + w)/2.0))
Haskell/pile.hs
push :: [Int] -> Int -> [Int]
push pilha x = x:pilha
pop :: [Int] -> [Int]
pop [] = error "Pilha vazia"
pop (x:xs) = xs
top :: [Int] -> Int
top [] = error "Pilha vazia"
top (x:xs) = x
is_empty :: [Int] -> Bool
is_empty [] = True
is_empty _ = False
Haskell/pie.cpp
/*Problema 3635 - UVA: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=19&page=show_problem&problem=1636*/
#include <iostream>
#include <cstdio>
#include <stack>
#include <queue>
#include <list>
#include <vector>
#include <map>
#include <utility>
#include <functional>
#include <algorithm>
#include <cmath>
#include <limits>
#define PI 3.141592653589793238463
#define sz(a) int((a).size()) 
#define pb push_back 
#define all(c) (c).begin(),(c).end() 
#define tr(c,i) for(typeof((c).begin()) (i) = (c).begin(); (i) != (c).end(); (i)++) 
#define present(c,x) ((c).find(x) != (c).end()) 
#define cpresent(c,x) (find(all(c),x) != (c).end()) 
#define I(x) ((int)(x))
using namespace std;
typedef vector<int> vi; 
typedef vector<vi > vvi; 
typedef pair<int,int> ii;
typedef pair<double,int> di;
typedef vector<string> vs; 
typedef vector<ii> vii;
typedef vector<di> vdi;
typedef vector< pair<double, ii> > vdii;
template <class T>
int N, F;
double r[10000];
class mycmp: less<T>{
	public:
		bool operator() (const T& e1, const T& e2)
		{
			if(e1.first > e2.first)
			{
				return true;
			}
			if(e1.first == e2.first)
			{
				if(e1.second < e2.second)
				{
					return true;
				}
			}
			return false;
		}
};
bool satisfaz(int a)
{
	int l, c;
	int somatorio = 0;
	for(i = 0; i < N; i++)
	{
		somatorio += I(r[i]/a);
	}
	return somatorio >= F;
}
bool fsatisfaz(int a)
{
	int l, c;
	int somatorio = 0;
	for(i = 0; i < N; i++)
	{
		somatorio += I(r[i]/a);
	}
	return somatorio >= F;
}
inline float satisfaz2(int a, int b)
{
	int i;
	float aux = 0.00000;
	cout << "Aux: " << aux;
	a = a*10000;
	b = b*10000;
	for(i = b; i >= a; i--)
	{
		aux = i;
		if(fsatisfaz(aux/10000.0000F))
		{
			return i;
		}
	}
	return -1;
}
inline float satisfaz3(float a, float b)
{
	int i;
	float aux = 0.0000;
	int c = a*10000;
	int d = b*10000;
	for(i = d; i >= c; i--)
	{
		aux = i;
		if(fsatisfaz(aux/10000.0000F))
		{
			return i;
		}
	}
	return -1;
}
int main()
{
	int T;
	int i, j;
	double m;
	int ini, fim, mid;
	cin >> T;
	while(T)
	{
		cin >> N >> F;
		F++;
		m = 1000000000;
		fini = ffim = 0.0000;
		for(i = 0; i < N; i++)
		{
			cin >> r[i];
			r[i] =* r[i]*PI;
			m = min(r[i], m);
		}
		m *= m*PI;
		if(!satisfaz(1))
		{
			cout << satisfaz2(0, 1);
		}
		else if(satisfaz(I(m)))
		{
			cout << satisfaz3(I(m), m);
		}
		else{
			ini = 1;
			fim = (int)m;
			while(ini < fim-1)
			{
				mid = (ini + fim)/2;
				if(satisfaz(mid))
				{
					ini = mid;
				}
				else
				{
					fim = mid;
				}
				cout << satisfaz2(ini, fim);
			}
			//o volume procurado esta entre ini e fim
		}
		T--;
	}
	return 0;
}
Haskell/operadores.hs
True && False --> e logico
True || False --> ou lógico
not True --> negação lógica
div 3 2 --> divisao inteira
mod 3 2 --> modulo
abs(-20) --> valor absoluto
-- relacionais
2 > 2
2 < 2
2 >= 2
2 <= 2
2 == 2
2 /= 2
-- operadores de caracteres
import Data.char
ord 'g' --> valor numerico do caractere g na tabela ASCII
chr 120 --> quem é 120 na tabelas ASCII?
isLower 'a' -->verifica se um caracter é minúsculo
isUpper 'A' --> verifica se um caracter é maiúsculo
toLower 'a' --> converte caractere a minúsculo
toUpper 'a' --> converte caractere a maiúsculo
isDigit '1' --> verifica se caracterer é digito
digitToInt '2' --> converte caracter digito a inteiro
intToDigit 2 --> converte digito inteiro a caracter
exp 2 --> e^2
fromIntegral 10 --> converte inteiro a real
log 10 --> log 10 na base e
sqrt 100 --> raiz quadrada
floor 3.8 --> arrendondamento para baixo
ceiling 3.8 --> arrendondamento para cima
round 4.5 --> arrendondamento
Haskell/new_types.hs
type Nome = String
type Linguagem = String
type Universidade = String
data Pessoa = Programador Nome Linguagem | Aluno Nome Universidade
				deriving(Show)
programador = Programador "Marcos" "Haskell"
aluno = Aluno "Marcos" "UFPI"
is_programador :: Pessoa -> Bool
is_programador (Programador _ _) = True
is_programador _ = False
is_aluno :: Pessoa -> Bool
is_aluno (Aluno _ _) = True
is_aluno _ = False
Haskell/my_comp.hs
comp_listas :: [Int] -> [Int] -> Bool
comp_listas [] [] = True
comp_listas (a:b) (c:d)
		| (a==c) = comp_listas b d
		|
otherwise = False
comp_listas _ _ = False
Haskell/ifthen_case.hs
if_par :: Int -> Bool
if_par n = if (mod n 2 == 0) then True else False
case_par :: Int -> Bool
case_par n = case (mod n 2 == 0) of
					True -> True
					False -> False
					
Haskell/hanoi.hs
--hanoiAux N origem auxiliar destino
--move os N-1 discos superiores para o auxiliar utilizando a torre destino como auxiliar
--move o disco inferior, o maior de todos para a origem
--move os N-1 discos restantes da torre intermediaria para a torre de destino
hanoiAux :: Int -> Char -> Char -> Char-> [[Char]]
hanoiAux 1 o a d = ["Move de " ++ [o] ++ " para " ++ [d]]
hanoiAux n o a d | n > 1 = (hanoiAux (n-1) o d a) ++ ["Move de " ++ [o] ++ " para " ++ [d]] ++ (hanoiAux (n-1) a o d)
				 | otherwise = []
hanoi :: Int -> [[Char]]
hanoi n = (hanoiAux n 'A' 'B' 'C')
Haskell/filter.hs
is_prime :: Int -> Bool
is_prime 1 = False
is_prime 2 = True
is_prime n | (length [x | x <- [2 .. n-1], mod n x == 0]) > 0 = False
		 | otherwise = True
-- uso: filter is_prime [1 .. n]
Haskell/f_lambda.hs
f_lambda = \x -> (x*x)
f x = x * x
Haskell/exercicios1_10.hs
{-myEq :: [t] -> [t] -> Bool
myEq [] [] = True
myEq [] _ = False
myEq _ [] = False
myEq (x:xs) (y:ys) | (x /= y) = False
				 | otherwise = myEq xs ys-}
--problem4
myLen :: [t] -> Int
myLen [] = 0
myLen (x:xs) = 1 + myLen xs
--problem1
myLast :: [t] -> t
myLast (x:xs) | (myLen (x:xs) == 1) = x
			 | otherwise = myLast xs
--problem2
myButLast :: [t] -> t
myButLast (x:xs) | (myLen(x:xs) == 2) = x
				 | otherwise = myButLast xs
--problem3
elementAt :: [t] -> Int -> t
elementAt (x:xs) n | (n == 1) = x
				 | (n > 1) = elementAt xs (n-1)
--problem5
myReverse :: [t] -> [t]
myReverse [] = []
myReverse (x:xs) = (myReverse xs)++[x]
--problem6
isPalindrome :: [Char] -> Bool
isPalindrome x | (x == (myReverse x)) = True
			 | otherwise = False
--problem7
data NestedList = Elem Int | List [NestedList]
is_elem :: NestedList -> Bool
is_elem (Elem _) = True
is_elem _ = False
get_elem :: NestedList -> Int
get_elem (Elem x) = x
myFlatten :: NestedList -> [Int]
myFlatten (Elem x) = [x]
myFlatten (List []) = []
myFlatten (List (x:xs)) | is_elem(x) = get_elem(x):myFlatten(List xs)
					 | otherwise = myFlatten(x) ++ myFlatten(List xs)
--problem8
myCompress :: [Char] -> [Char]
myCompress [] = []
myCompress (x:[]) = [x]
myCompress (x:(y:ys)) | x == y = myCompress(y:ys)
					 | otherwise = x:(myCompress(y:ys))
--problem9
packAux :: [Char] -> [Char] -> [[Char]]
packAux [] [] = []
packAux (x:[]) [] = [[x]]
packAux [] (x:[]) = [[x]]
packAux (x:xs) [] = [(x:xs)]
packAux [] (x:xs) = packAux [x] xs
packAux (x:xs) (y:ys) | x == y = packAux (y:(x:xs)) ys
					 | otherwise = (x:xs):(packAux [] (y:ys))
pack :: [Char] -> [[Char]]
pack x = packAux [] x
{-- 
Exemplo:
pack ['a', 'a', 'a', 'a', 'b', 'c', 'c', 'a', 'a', 'd', 'e', 'e', 'e']
 = packAux [] ['a', 'a', 'a', 'a', 'b', 'c', 'c', 'a', 'a', 'd', 'e', 'e', 'e']
 = packAux ['a'] ['a', 'a', 'a', 'b', 'c', 'c', 'a', 'a', 'd', 'e', 'e', 'e']
 = packAux ['a', 'a'] ['a', 'a', 'b', 'c', 'c', 'a', 'a', 'd', 'e', 'e', 'e']
 = packAux ["aaa"] ['a', 'b', 'c', 'c', 'a', 'a', 'd', 'e', 'e', 'e']
 = packAux ["aaaa"] ['b', 'c', 'c', 'a', 'a', 'd', 'e', 'e', 'e']
 = ["aaaa"]:(packAux [] ['b', 'c', 'c', 'a', 'a', 'd', 'e', 'e', 'e'])
 = ["aaaa"]:(packAux ['b'] ['c', 'c', 'a', 'a', 'd', 'e', 'e', 'e'])
 = ["aaaa"]:(['b']:(packAux [] ['c', 'c', 'a', 'a', 'd', 'e', 'e', 'e']))
 = ["aaaa"]:(['b']:(packAux ['c'] ['c', 'a', 'a', 'd', 'e', 'e', 'e']))
 = ["aaaa"]:(['b']:(packAux ["cc"] ['a', 'a', 'd', 'e', 'e', 'e']))
 = ["aaaa"]:(['b']:(("cc"):(packAux [] ['a', 'a', 'd', 'e', 'e', 'e']))
 = ("aaaa"):(['b']:(("cc"):(packAux ['a'] ['a', 'd', 'e', 'e', 'e']))
 = ["aaaa"]:(['b']:(("cc"):(packAux ("aa") ['d', 'e', 'e', 'e']))
 = ["aaaa"]:(['b']:(("cc"):(("aa"):(packAux [] ['d', 'e', 'e', 'e'])) )
 --}
--problem10
encodeAux :: [[Char]] -> [(Int,Char)]
encodeAux [] = []
encodeAux ((x:xs):ys) = ((myLen (x:xs)), x):(encodeAux ys)
encode :: [Char] -> [(Int,Char)]
encode x = encodeAux (pack x)
--problem11
data Compression = Single Char | Multiple Int Char
					deriving(Show)
encodeModifiedAux :: [[Char]] -> [Compression]
encodeModifiedAux [] = []
encodeModifiedAux((x:xs):ys) | (myLen (x:xs)) == 1 = (Single x):(encodeModifiedAux ys)
							 | otherwise = (Multiple (myLen(x:xs)) x):(encodeModifiedAux ys)
encodeModified :: [Char] -> [Compression]
encodeModified x = encodeModifiedAux (pack x)
Haskell/exemplo_carros.hs
type Pessoa = String
type Carro = String
type Idade = Int
type Registro = (Pessoa, Carro, Idade)
type BD = [Registro]
f_bd :: BD
f_bd = [("Joao", "Camaro", 20), ("Maria", "Fusca", 30)]
getNome :: Registro -> Pessoa
getNome (n, _, _) = n
getCarros :: BD -> [String]
getCarros ((_, carro, _):xs) = carro : getCarros xs --> retorna lista de todos os carros
Haskell/exemploDo.hs
putStrLn:: String -> IO()
putStrLn str = do putStr str
				 putStr "\n"
faz4vezes::String -> IO()
faz4vezes str = do putStrLn str
				 putStrLn str
				 putStrLn str
				 putStrLn str
fazNvezes :: Int -> String -> IO()
fazNvezes n str = if n <= 1 then putStrLn str
							else do putStrLn str
									fazNvezes (n-1) str
leia2Linhas :: IO()
leia2Linhas = do getLine
				 getLine
				 putStrLn "duas linhas lidas"
getNput :: IO()
getNput = do linha1 <- getLine
			 linha2 <- getLine
			 putStrLn linha1
			 putStrLn linha2
Haskell/arvbusbin.hs
data ArvBusBin t = Nil | No (ArvBusBin t) t (ArvBusBin t)
						deriving (Show, Ord, Eq)
arvbusbin1 = No (No Nil 9 Nil) 14 (No Nil 19 (No Nil 51 Nil))
arvbusbin2 = No (No Nil 3 Nil) 7 (No Nil 18 (No Nil 27 Nil))
arvBBtolista :: ArvBusBin t -> [t]
arvBBtolista Nil = []
arvBBtolista (No ae n ad) = arvBBtolista ae ++ [n] ++ arvBBtolista ad
membroABB :: (Ord t) => t -> ArvBusBin t -> Bool
membroABB :: x Nil = False
membroABB :: x (No ae y ad)
			| x == y = True
			| x != y = (membroABB x ae) || (membroABB x ad)
altABB :: (Ord t) => ArvBusBin t -> Int
altABB Nil = 0
altABB (No ae n ad)
	|ae == Nil) && (ad == Nil) = 0
	| otherwise 1 + max (altABB ae) (altABB ad)
fazABB :: (Ord t) => [t] -> ArvBusBin t
fazABB :: [] = Nil
fazABB (x:xs) = No (fazABB ys) x (fazABB zs)
						| where (ys,zs) = particao (<=x) xs
particao :: (Ord t) => (t->Bool) -> [t] -> ([t],[t])
partica p xs = (filter p xs, filter (not.p) xs)
sort :: (Ord t) => [t] -> [t]
sort = arvBBtolista.fazABB
remove :: (Ord t) => t -> ArvBusBin t -> ArvBusBin t
remove x Nil = Nil
remove x (No ae n ad)
	| (x<n) = No (remove x ae) n ad
	| (x>n) = No ae n (remove x ad)
	| (x==n) = junta ae ad
junta :: (Ord t) => ArvBusBin t -> ArvBusBin t -> ArvBusBin t
junta Nil yt = yt
junta (No ut x vt) yt = No ut x (junta yt vt)
Haskell/arvbin.hs
--Nos externos = nos internos + 1
data ArvBin = Nulo | No Int ArvBin ArvBin
arv :: ArvBin
arv = (No 1 
		(No 2(No 4 Nulo Nulo) (No 5 Nulo Nulo))
		(No 3(No 6 Nulo Nulo) Nulo))
em_ordem :: ArvBin -> [Int]
em_ordem Nulo = []
em_ordem (No num esq dir) = (em_ordem esq) ++ [num] ++ (em_ordem dir)
Haskell/array.hs
import Data.Array
get_array = array (1, 4) [(1,'A'), (2, 'B'), (3, 'C'), (4, 'D')]
-- elems get_array --> retorna os elementos do array
-- get_array ! 2 --> elemento da posicao 2
-- bounds get_array --> retorna limites do array
get_matriz = array ((1,1),(2,2)) [((1,1), 'A'), ((1,2), 'B'), ((2,1), 'C'), ((2,2), 'D')]
Haskell/3nmaisum.hs
par :: Int -> Bool
par x | ((mod x 2) == 0) = True
	 | otherwise = False
tamciclo :: Int -> Int
tamciclo 1 = 1
tamciclo x | (par(x) == True) = (1+tamciclo((x `div` 2)))
		 | otherwise = (1+tamciclo(((3*x) + 1)))
Haskell/haskell problems.odt
http://www.haskell.org/haskellwiki/99_questions/1_to_10
1 Problem 1 
(*) Find the last element of a list. 
(Note that the Lisp transcription of this problem is incorrect.) 
Example in Haskell: 
Prelude> myLast [1,2,3,4]
4
Prelude> myLast ['x','y','z']
'z'
Solutions 
2 Problem 2 
(*) Find the last but one element of a list. 
(Note that the Lisp transcription of this problem is incorrect.) 
Example in Haskell: 
Prelude> myButLast [1,2,3,4]
3
Prelude> myButLast ['a'..'z']
'y'
Solutions 
3 Problem 3 
(*) Find the K'th element of a list. The first element in the list is number 1. 
Example: 
* (element-at '(a b c d e) 3)
c
Example in Haskell: 
Prelude> elementAt [1,2,3] 2
2
Prelude> elementAt "haskell" 5
'e'
Solutions 
4 Problem 4 
(*) Find the number of elements of a list. 
Example in Haskell: 
Prelude> myLength [123, 456, 789]
3
Prelude> myLength "Hello, world!"
13
Solutions 
5 Problem 5 
(*) Reverse a list. 
Example in Haskell: 
Prelude> myReverse "A man, a plan, a canal, panama!"
"!amanap ,lanac a ,nalp a ,nam A"
Prelude> myReverse [1,2,3,4]
[4,3,2,1]
Solutions 
6 Problem 6 
(*) Find out whether a list is a palindrome. A palindrome can be read forward or backward; e.g. (x a m a x). 
Example in Haskell: 
*Main> isPalindrome [1,2,3]
False
*Main> isPalindrome "madamimadam"
True
*Main> isPalindrome [1,2,4,8,16,8,4,2,1]
True
Solutions 
7 Problem 7 
(**) Flatten a nested list structure. 
Transform a list, possibly holding lists as elements into a `flat' list by replacing each list with its elements (recursively). 
Example: 
* (my-flatten '(a (b (c d) e)))
(A B C D E)
Example in Haskell: 
We have to define a new data type, because lists in Haskell are homogeneous. 
data NestedList a = Elem a | List [NestedList a]
*Main> flatten (Elem 5)
[5]
*Main> flatten (List [Elem 1, List [Elem 2, List [Elem 3, Elem 4], Elem 5]])
[1,2,3,4,5]
*Main> flatten (List [])
[]
Solutions 
8 Problem 8 
(**) Eliminate consecutive duplicates of list elements. 
If a list contains repeated elements they should be replaced with a single copy of the element. The order of the elements should not be changed. 
Example: 
* (compress '(a a a a b c c a a d e e e e))
(A B C A D E)
Example in Haskell: 
> compress "aaaabccaadeeee"
"abcade"
Solutions 
9 Problem 9 
(**) Pack consecutive duplicates of list elements into sublists. If a list contains repeated elements they should be placed in separate sublists. 
Example: 
* (pack '(a a a a b c c a a d e e e e))
((A A A A) (B) (C C) (A A) (D) (E E E E))
Example in Haskell: 
*Main> pack ['a', 'a', 'a', 'a', 'b', 'c', 'c', 'a', 
'a', 'd', 'e', 'e', 'e', 'e']
["aaaa","b","cc","aa","d","eeee"]
Solutions 
10 Problem 10 
(*) Run-length encoding of a list. Use the result of problem P09 to implement the so-called run-length encoding data compression method. Consecutive duplicates of elements are encoded as lists (N E) where N is the number of duplicates of the element E. 
Example: 
* (encode '(a a a a b c c a a d e e e e))
((4 A) (1 B) (2 C) (2 A) (1 D)(4 E))
Example in Haskell: 
encode "aaaabccaadeeee"
[(4,'a'),(1,'b'),(2,'c'),(2,'a'),(1,'d'),(4,'e')]
http://www.haskell.org/haskellwiki/99_questions/11_to_20
1 Problem 11 
(*) Modified run-length encoding. 
Modify the result of problem 10 in such a way that if an element has no duplicates it is simply copied into the result list. Only elements with duplicates are transferred as (N E) lists. 
Example: 
* (encode-modified '(a a a a b c c a a d e e e e))
((4 A) B (2 C) (2 A) D (4 E))
Example in Haskell: 
P11> encodeModified "aaaabccaadeeee"
[Multiple 4 'a',Single 'b',Multiple 2 'c',
Multiple 2 'a',Single 'd',Multiple 4 'e']
Solutions 
2 Problem 12 
(**) Decode a run-length encoded list. 
Given a run-length code list generated as specified in problem 11. Construct its uncompressed version. 
Example in Haskell: 
P12> decodeModified 
[Multiple 4 'a',Single 'b',Multiple 2 'c',
Multiple 2 'a',Single 'd',Multiple 4 'e']
"aaaabccaadeeee"
Solutions 
3 Problem 13 
(**) Run-length encoding of a list (direct solution). 
Implement the so-called run-length encoding data compression method directly. I.e. don't explicitly create the sublists containing the duplicates, as in problem 9, but only count them. As in problem P11, simplify the result list by replacing the singleton lists (1 X) by X. 
Example: 
* (encode-direct '(a a a a b c c a a d e e e e))
((4 A) B (2 C) (2 A) D (4 E))
Example in Haskell: 
P13> encodeDirect "aaaabccaadeeee"
[Multiple 4 'a',Single 'b',Multiple 2 'c',
Multiple 2 'a',Single 'd',Multiple 4 'e']
Solutions 
4 Problem 14 
(*) Duplicate the elements of a list. 
Example: 
* (dupli '(a b c c d))
(A A B B C C C C D D)
Example in Haskell: 
> dupli [1, 2, 3]
[1,1,2,2,3,3]
Solutions 
5 Problem 15 
(**) Replicate the elements of a list a given number of times. 
Example: 
* (repli '(a b c) 3)
(A A A B B B C C C)
Example in Haskell: 
> repli "abc" 3
"aaabbbccc"
Solutions 
6 Problem 16 
(**) Drop every N'th element from a list. 
Example: 
* (drop '(a b c d e f g h i k) 3)
(A B D E G H K)
Example in Haskell: 
*Main> dropEvery "abcdefghik" 3
"abdeghk"
Solutions 
7 Problem 17 
(*) Split a list into two parts; the length of the first part is given. 
Do not use any predefined predicates. 
Example: 
* (split '(a b c d e f g h i k) 3)
( (A B C) (D E F G H I K))
Example in Haskell: 
*Main> split "abcdefghik" 3
("abc", "defghik")
Solutions 
8 Problem 18 
(**) Extract a slice from a list. 
Given two indices, i and k, the slice is the list containing the elements between the i'th and k'th element of the original list (both limits included). Start counting the elements with 1. 
Example: 
* (slice '(a b c d e f g h i k) 3 7)
(C D E F G)
Example in Haskell: 
*Main> slice ['a','b','c','d','e','f','g','h','i','k'] 3 7
"cdefg"
Solutions 
9 Problem 19 
(**) Rotate a list N places to the left. 
Hint: Use the predefined functions length and (++). 
Examples: 
* (rotate '(a b c d e f g h) 3)
(D E F G H A B C)
* (rotate '(a b c d e f g h) -2)
(G H A B C D E F)
Examples in Haskell: 
*Main> rotate ['a','b','c','d','e','f','g','h'] 3
"defghabc"
 
*Main> rotate ['a','b','c','d','e','f','g','h'] (-2)
"ghabcdef"
Solutions 
10 Problem 20 
(*) Remove the K'th element from a list. 
Example in Prolog: 
?- remove_at(X,[a,b,c,d],2,R).
X = b
R = [a,c,d]
Example in Lisp: 
* (remove-at '(a b c d) 2)
(A C D)
(Note that this only returns the residue list, while the Prolog version also returns the deleted element.) 
Example in Haskell: 
*Main> removeAt 2 "abcd"
('b',"acd")
Haskell/quant_perfeitos.hs
eDivisor :: Int -> Int -> Bool
eDivisor x y | (x `mod` y == 0) = True
			 | otherwise = False
aux :: Int -> Int -> Int
aux x 1 = 1
aux x y | y <= 0 = 0
		| (eDivisor x y) = (y + (aux x (y-1)))
		| otherwise = (aux x (y-1))
somaDivisores :: Int -> Int
somaDivisores n = (aux n (n `div` 2))
ePerfeito :: Int -> Bool
ePerfeito n = (n == somaDivisores(n))
perfeitosAux :: Int -> Int -> [Int]
perfeitosAux x 0 = []
perfeitosAux x 1 | ePerfeito(x) = [x]
				 | otherwise = perfeitosAux (x+1) 1
perfeitosAux x y | ePerfeito(x) = x:(perfeitosAux (x+1) (y-1))
				 | otherwise = perfeitosAux (x+1) y
quantPerfeitos :: Int -> [Int]
quantPerfeitos 1 = [6]
quantPerfeitos n | n > 1 = 6:(perfeitosAux 7 (n-1))
Haskell/zip.hs
-- zip :: [a] -> [b] -> [(a,b)]
zip [1,2,3] [a,b,c]
-- gera [(1,a), (2,b), (3,c)]
Haskell/tuple.hs
tuple :: (Int, Int) -> (Int, Int) -> (Int,
Int)
tuple (a, b) (c, d) = (a + c, b + d)
Haskell/exercicios_list.hs
Haskell/ordenacao.hs
get_menor :: [Int] -> Int
get_menor [x] = x
get_menor (x:xs) | (x < get_menor xs) = x
				 | otherwise = get_menor xs
remove_menor :: [Int] -> [Int]
remove_menor [] = []
remove_menor (x:xs) | (x == get_menor (x:xs)) = xs
					| otherwise (x:remove_menor xs)
aux_ordena :: [Int] -> [Int]
aux_ordena lista_ordenada [] = lista_ordenada
aux_ordena lista_ordenada x = aux_ordena (lista_ordenada++[get_menor x]) (remove_menor x)
ordena :: [Int] -> [Int]
ordena [] = []
ordena x = aux_ordena [] x
Haskell/rev_list.hs
inv_aux :: [t] -> [t] -> [t]
inv_aux [] l_inv = l_inv
inv_aux (x:xs) l_inv = inv_aux xs l_inv++[x] --operador ++ concatena listas necessario transformar x em lista usando []
inv_lista :: [t] -> [t]
inv_lista [] = []
inv_lista l = inv_aux l []
rev_list :: [t] -> [t]
rev_list [] = []
rev_list (x:xs) = rev_list xs ++ [x] -- recursao a esquerda
Haskell/comp_listas.hs
comp_listas :: [Int] -> [Int] -> Bool
comp_listas [] [] = True
comp_listas [] _ = False
comp_listas _ [] = False
comp_listas (x:xs) (y:ys) | (x == y) = comp_listas xs ys
						 | otherwise = False
Haskell/anom_and.hs
e :: Bool -> Bool -> Bool
e False _ = False
e _ False = False
e True True = True
Haskell/guarda.hs
guarda x | (x == 0) = 0
		 | (x == 1) = 1
		 | otherwise = 10
Haskell/fatorial.hs
fatorial 0 = 1
fatorial n = n*fatorial(n-1)
Haskell/tuple_ops.hs
-- fst ("marcos", 73) --extrai primeiro elemento de uma tupla
-- snd ("marcos", 73) --extrai segundo elemento de uma tupla de dois elementos
nomes :: (String, String, String)
nomes = ("Marcos", "Geeksbr", "Haskell")
selec_prim(x, _, _) = x
selec_sec(_, y, _) = y
selec_ter(_, _, z) = z
Haskell/list_len.hs
size_list [] = 0
size_list (x:xs) = 1 + size_list(xs)
Haskell/list_ops.hs
pertence :: [Int] -> Int -> Bool
pertence [] _ = False
pertence (x:xs) n | (x == n) = True
				 | otherwise = pertence xs n
maior :: [Int] -> Int
maior [x] = x
maior (x:xs) | (x > maior xs) = x
			 | otherwise = maior xs
todos_pares :: [Int] -> Bool
todos_pares [] = True
todos_pares (x:xs) | (mod x 2 /= 0) = False
				 | otherwise = todos_pares xs
Haskell/soma_numeros.hs
soma 1 = 1
soma n = soma(n-1) + 1
Haskell/list_comprehension.hs
[x | x <- [1 .. 10], (mod x 2) == 0]
[(x,y) | x <- [2 .. 5], y <- [4 .. 9]]
Haskell/type.hs
type Nome = String
type Idade = Int
type Linguagem = String
type Pessoa = (Nome, Idade, Linguagem)
pessoa:: Pessoa
pessoa = ("joao", 20, "haskell")
my_fst :: Pessoa -> Nome
my_fst (n, i, l) = n
Haskell/fibonacci.hs
fibonacci 0 = 1
fibonacci 1 = 1
fibonacci n = fibonacci (n - 1) + fibonacci (n - 2)
Haskell/lista 2/um.hs
{--
A implementação deste item foi realizada utilizando uma função f2 auxiliar, 
que retorna a lista de elementos a ser concatenada baseada no vetor de posições, 
e a função utilitária map. A função map juntamente com a função implementada dec 
foi usada por conveniencia, para realizar a indexação dos elementos a partir de 
um, embora por default o operador !! use indexação baseada em zero. Adicionalmente
utilizamos a funcao reverse para imprimir os elementos extras na ordem especifica-
da.
--}
dec :: Int -> Int
dec x = x-1
f2 :: [Int] -> [t] -> [t]
f2 [] (y:ys) = []
f2 (x:xs) (y:ys) = ((y:ys)!!x):(f2 xs (y:ys))
f :: [Int] -> [t] -> [t]
f [] [] = []
f (x:xs) [] = []
f [] (y:ys) = (y:ys)
f (x:xs) (y:ys) = (y:ys)++(reverse(f2 (map (dec) (x:xs)) (y:ys)))
Haskell/lista 2/tres.hs
import Data.Matrix
my_sum :: (Num t) => [t] -> Int -> t
my_sum [] _ = 0
my_sum (x:xs) 1 = x + (my_sum xs (-1))
my_sum (x:xs) (-1) = (-1)*x + (my_sum xs 1)
my_minor :: (Num t) => Matrix t -> Int -> Matrix t
my_minor x a = minorMatrix 1 a x 
my_det :: (Num t) => Matrix t -> t
my_det x | (nrows x) == 2 = ((getElem 1 1 x)*(getElem 2 2 x) - (getElem 1 2 x)*(getElem 2 1 x))
		 | otherwise = (my_sum (map (my_det) (map (my_minor x) [1 .. (ncols x)])) 1)
mat :: Matrix Int
mat = fromList 3 3 [1..]
{--
Na implementação deste exercício foi utilizada a biblioteca Data.Matrix,
que pode ser instalada no linux com o utilitário cabal(apt-get install cabal-install) 
com o comando cabal install matrix.
Instrucoes de instalacao do cabal no windows podem ser encontradas em:
http://www.haskell.org/haskellwiki/Cabal-Install#Windows
Com a declaração de mat é possível realizar o teste da função my_det que recebe como 
argumento uma matriz de números e retorna o determinante dessa matriz, que no caso é zero. 
Foi utilizada a ideia recursiva de que o determinante de uma matriz é igual ao somatório 
do determinante multiplicado por um fator, que se alterna entre -1 e 1(função my_sum) das
submatrizes obtidas escolhendo-se uma linha e removendo, isoladamente, a coluna e o 
elemento de cada elemento desta linha até a coluna ncols x , onde x é uma matriz 
passada como parâmetro.
--}
Haskell/lista 2/sete.hs
pred_length :: Int -> [t] -> Bool
pred_length n x = (length x) >= n
list_sub :: [t] -> Int -> [[t]]
list_sub [] _ = [[]]
list_sub (x:xs) n | (length (x:xs)) >= n = filter (pred_length n) ([x:y | y <- (list_sub xs (n-1))] ++ (list_sub xs n) ) 
					| otherwise = [[]]
{--
Para retornar todas as sublistas de uma lista de elementos, tal que essas sublistas tenham um tamanho
maior ou igual que um número n eh necessário percorrer todo o espaço de busca. Recursivamente, podemos definir 
todas essas combinacoes em uma lista haskell do tipo (x:xs) como o conjunto de todas as sublistas de 
tamanho maiores ou iguais que n que nao contem a cabeça x unido ao conjunto das sublistas da concatenacao
da cabeça x a todas as sublistas possiveis de tamanho maior ou igual a n-1 na lista xs. A funcao filter garante a 
propriedade “>=n”, enquanto a condicao (length (x:xs)) >= n foi utilizada para fins de desempenho, podando 
onde as cadeias nao podem alcançar a longitude minima desejada.
--}
Haskell/lista 2/seis.hs
nove :: [Int]
nove = [4,1,4,2,1,2,1]
cinco :: [Int]
cinco = [4,2,3,2,4]
um :: [Int]
um = [0,2,1,2,1,2,1,2,1,2,1]
dois :: [Int]
dois = [3,2,5,2,3]
tres :: [Int]
tres = [3,2,4,2,4] 
quatro :: [Int]
quatro = [1,1,2,1,4,2,1,2,1]
seis :: [Int]
seis = [4,2,4,1,4]
sete :: [Int]
sete = [3,2,1,2,1,2,1,2,1]
oito :: [Int]
oito = [4,1,5,1,4]
zero :: [Int]
zero = [4,1,2,1,2,1,4]
-- Letra a
toAst :: Int -> String
toAst 0 = ""
toAst n = "*"++(toAst (n-1))
toSpace :: Int -> String
toSpace 0 = ""
toSpace n = " "++(toSpace (n-1))
toString :: [Int] -> String
toString [] = ""
toString (x:[]) = toAst x
toString (x:y:ys) = (toAst x) ++ (toSpace y) ++ (toString ys)
--Letra b
type Linha = String
toLinhas :: String -> [Linha]
toLinhas [] = []
toLinhas (x:[]) = [[x]]
toLinhas (x:y:z:zs) = [x,y,z]:(toLinhas zs)
--Letra c
showLinhas :: [Linha] -> String
showLinhas [] = ""
showLinhas (x:xs) = x++"\n"++(showLinhas xs)
--Letra d
juntaLinhas :: [Linha] -> [Linha] -> [Linha]
juntaLinhas [] [] = []
juntaLinhas (x:xs) (y:ys) = (x++" "++y):(juntaLinhas xs ys)
--Letra e
ndig :: Int -> Int
ndig n | n < 10 = 1
 | n < 100 = 2
 | otherwise = 3
numeros :: [[Int]]
numeros = [zero,um,dois,tres,quatro,cinco,seis,sete,oito,nove]
tolcd :: Int -> String
tolcd n | (ndig n) == 1 = showLinhas (toLinhas (toString (numeros!!n)))
 | (ndig n) == 2 
 = showLinhas
 (juntaLinhas 
 (toLinhas (toString (numeros!!((mod n 100) `div` 10)))) 
 (toLinhas (toString (numeros!!(mod n 10))))
 )
 | (ndig n) == 3 
 = showLinhas
 (juntaLinhas 
 (juntaLinhas
 (toLinhas 
 (toString (numeros!!((mod n 1000) `div` 100))))
(toLinhas 
 (toString (numeros!!((mod n 100) `div` 10)))) ) 
 (toLinhas (toString (numeros!!((mod n 10)))))
 )
--Letra f
type Estado = Bool
tcomp :: String -> Estado -> Int -> [Int]
tcomp [] False n | (n > 0) = [n]
 | otherwise = []
tcomp [] True n | (n > 0) = [n]
 | otherwise = []
tcomp (x:xs) True n | x == '*' = tcomp (xs) True (n+1)
 | otherwise = n:(tcomp (x:xs) False 0)
tcomp (x:xs) False n | x == ' ' = tcomp (xs) False (n+1)
 | otherwise = n:(tcomp (x:xs) True 0)
toCompact :: String -> [Int]
toCompact s = tcomp s True 0
Haskell/lista 2/quatro.hs
validAux :: Int -> Int -> [Int] -> Bool
validAux _ _ [] = True
validAux p c (x:xs) | p == x = False --rainhas na mesma linha
					| ((x-p) == c) || ((x-p) == (-c)) = False -- rainhas na mesma diagonal
					| otherwise = validAux p (c+1) xs
valid :: [Int] -> Bool
valid [] = True
valid (x:xs) = (validAux x 1 xs) && (valid xs)
--chess8Aux n
--resolve problema das 8 rainhas. O parametro n eh o numero de colunas restantes
chess8Aux :: Int -> [[Int]]
chess8Aux 0 = [[]]
chess8Aux 1 = [[1]]
chess8Aux n = filter valid [x:y | y <- (chess8Aux (n-1)), x <- [1 .. 8]]
chess8 :: [Int]
chess8 = (chess8Aux 8)!!1
{--
As funções valid e validAux são usadas com propósito de filtrar o espaço de configurações do tabuleiro 
de modo que as rainhas não conflitem em linha ou diagonal. A verificação por coluna não é necessária 
visto que é considerado que as rainhas são colocadas por padrão em colunas distintas, sendo o retorno 
de chess8 uma lista com as posições das linhas das rainhas em ordem de colunas. A função chess8Aux 
retorna um conjunto de soluções possíveis quando passada com o parâmetro 8, e a função chess retorna 
a solução de posição 1 na lista de listas retornada por chess8Aux.
--}
Haskell/lista 2/oito.hs
occur :: String -> String -> String -> Bool
occur [] _ _ = True
occur x _ [] = True
occur _ [] _ = False
occur x (y:ys) (a:as) | y == a = occur x ys as
				 | otherwise = occur x (ys) x
getT :: Int -> (String, String) -> String
getT 0 (a,b) = a
getT 1 (a,b) = b
-- sep x y z b c
-- retorna uma tupla contendo as string anteriores e posteriores a string x na cadeia y
-- x: A string a ser encontrada
-- y: String onde deveremos buscar a String x
-- z: Restante dos caracteres de x a serem reconhecidos
-- b: Parte da String que coincidiu com o inicio de x, porem ainda esta em reconhecimento
-- c: Parte da String que foi lida mas que nao foi reconhecida
sep :: String -> String -> String -> String -> String -> (String, String)
sep [] y _ _ _= (y, [])
sep x y [] b c = (c, y)
sep _ [] _ b c = ((c++b), [])
sep x (y:ys) (a:as) b c | y == a = sep x ys as (b++[a]) c
				 		| otherwise = sep x ys x [] (c++b++[y])
substr :: String -> String -> String -> String
substr x y z | (occur x z x) = (getT 0 (sep x z x [] [])) ++ y ++ (getT 1 (sep x z x [] []))
		 | otherwise = z
{--
Para implementar o reconhecimento de strings, podemos simular um autômato que reconheça a substring1
na substring3 fazendo com que os estados do automato correspondam aos caracteres da substring1,
realizando a transicao dos caracteres um a um. Mantemos a string a ser reconhecida em memoria como 
o primeiro parâmetro da função occur e a cada passo fazemos uma chamada recursiva para a mesma, que 
equivale a uma transicao. O estado atual eh mantido na cabeca da lista correspondente ao terceiro 
parametro, juntamente com o restante a ser reconhecido. Quando não nos restam mais caracteres a 
serem reconhecidos(O terceiro parâmetro é a lista vazia), temos a certeza de que reconhecemos todos os 
caracteres e a substring1 pertence a substring3. Apos o reconhecimento, podemos realizar a 
substituicao com segurança. Em primeiro lugar separamos a string nas duas partes para a esquerda 
e para a direita da substring1, utilizando a função sep. Por ultimo, a funcao substr realiza o resto 
do trabalho concatenando a substring2 no meio das duas substrings resultantes de sep.
--}
Haskell/lista 2/nove.hs
type Pessoa = String
type Key = String
type Keys = [Key]
type Nome = String
type Database = [(Pessoa, Livro)]
--Tipos para letra c:
type Dia = Integer
type Mes = Integer
type Ano = Integer
type Data = (Dia, Mes, Ano)
type Livro = (String, Keys, Data) -- Letra b: Acrescentar chaves
numEmprestados :: Database -> Pessoa -> Int
numEmprestados db fulano = length [liv | (pes,liv) <- db, pes == fulano]
livrosEmprestados :: Database -> Pessoa -> [Livro]
livrosEmprestados db fulano = [liv | (pes, liv) <- db, pes == fulano]
--Letra a: Quantidade de livros emprestados deve ser menor ou igual que maxL, o numero maximo que alguem deve tomar emprestado
tomaEmprestado :: Database -> Pessoa -> Livro -> Database
tomaEmprestado db fulano titulo | ((numEmprestados db fulano) < maxL) = (fulano, titulo) : db
								| otherwise = db
--Funcao modificada para facilitar a devolucao do livro apenas pelo nome do livro
devolveLivro :: Database -> Pessoa -> Nome -> Database
devolveLivro ((p, (t,k,d)): r) f l
			|(p == f) && (t == l) = r
			| otherwise = (p,(t,k,d)) : devolveLivro r f l 
devolveLivro [ ] ful tit = error "Nao ha livro emprestado"
--Se livro ocorre no vetor de chaves retorna True. False Caso contrario.
occur :: Key -> Keys -> Bool
occur x (y:ys) | (x == y) = True
			 | otherwise = occur x ys
occur x [] = False
estaEmprestado :: Database -> Nome -> Bool
estaEmprestado db nome = (length [n | (_, (n, k, d)) <- db, n == nome]) > 0
--Letra b: Os livros podem ser encontrados atraves de palavras-chaves associadas a eles
buscarLivro :: Database -> Key -> [Livro]
buscarLivro db k = [(t,l,d) | (_, (t,l,d)) <- db, (occur k l)]
toDias :: Data -> Integer
toDias (d,m,a) = (d + (m*30) + (a*365))
devedores :: Database -> Data -> Nome -> [Pessoa]
devedores db atual l_name = [p | (p, (l,k,d)) <- db, (l == l_name), ((toDias atual) - (toDias d)) > maxD]
--Letra c: Livros atrasados podem ser encontrados
livrosAtrasados :: Database -> Data -> [Livro]
livrosAtrasados db atual = [(l,k,d) | (_, (l,k,d)) <- db, ((toDias atual) - (toDias d)) > maxD]
--Letra c: A lista de livros emprestados a uma determinada pessoa pode ser ordenada por data 
ordLivros :: [Livro] -> [Livro]
ordLivros ((pes, keys, dat):xs) = ((ordLivros [(p,k,d) | (p,k,d) <- xs, (toDias d) < (toDias dat)]) ++ [(pes, keys, dat)]) ++ (ordLivros [(p,k,d) | (p,k,d) <- xs, (toDias d) >= (toDias dat)])
ordLivros [] = []
livrosEmprestadosOrd :: Database -> Pessoa -> [Livro]
livrosEmprestadosOrd db p = ordLivros (livrosEmprestados db p)
-- maxL: Numero maximo de livros a serem emprestados
maxL :: Int
maxL = 3
-- maxD: Numero maximo de dias de um emprestimo
maxD :: Integer
maxD = 7
teste = [("Paulo", ("A Mente Nova do Rei", ["IA", "Roger Penrose", "Computador"], (12,6,2014))),
		("Ana", ("O Segredo de Luiza",["Empreendedorismo", "Fernando Dolabela"], (15, 5, 2014))),
		("Paulo", ("O Pequeno Principe", ["Antoine de Saint-Exupery", "Le Petit Prince", "historia"], (28, 6, 2014))), 
		("Mauro", ("O Capital", ["Karl Marx", "Das Kapital", "Socialismo"], (25, 6, 2014))),
		("Francisco", ("O Auto da Compadecida", ["Ariano Suassuna","Peça Teatral"], (22, 6, 2014))),
		("Paulo", ("O Cacador de Pipas", ["historia", "Khaled Hosseini", "Afeganistao"], (12,6,2014)))]
datual :: Data
datual = (30, 6, 2014)
Haskell/lista 2/lista_2_Milton.zip
cinco.hs
f2 :: [t] -> Bool -> [[t]] -> [[t]]
f2 [] _ x = x
f2 (x:xs) True [a, b] = f2 xs False [a++[x], b]
f2 (x:xs) False [a, b] = f2 xs True [a, b++[x]]
f :: [t] -> [[t]]
f x = f2 x True [[], []]
{--
As funções valid e validAux são usadas com propósito de filtrar o espaço de configurações 
do tabuleiro de modo que as rainhas não conflitem em linha ou diagonal. A verificação por 
coluna não é necessária visto
que é considerado que as rainhas são colocadas por padrão 
em colunas distintas, sendo o retorno de chess8 uma lista com as posições das linhas das 
rainhas em ordem consecutiva de colunas. A função chess8Aux retorna um conjunto de soluções possíveis
quando passada com o parâmetro 8, e a função chess retorna a solução de posição 1 na lista
de listas retornada por chess8Aux.
--}
dez.hs
sub_lists :: [t] -> [[t]]
sub_lists [] = [[]]
sub_lists (x:xs) = [x:y | y <- (sub_lists xs)] ++ (sub_lists xs)
{--
O conjunto de todas as sublistas e subsequencias possiveis da lista (x:xs)
eh a uniao entre o conjunto de todas as sublistas de (xs) e o conjunto de 
todas as concatenacoes [x]++y, tal que y pertence ao conjunto de todas as
sublistas e subsequencias de xs.
--}
nove.hs
type Pessoa = String
type Key = String
type Keys = [Key]
type Nome = String
type Database = [(Pessoa, Livro)]
--Tipos para letra c:
type Dia = Integer
type Mes = Integer
type Ano = Integer
type Data = (Dia, Mes, Ano)
type Livro = (String, Keys, Data) -- Letra b: Acrescentar chaves
numEmprestados :: Database -> Pessoa -> Int
numEmprestados db fulano = length [liv | (pes,liv) <- db, pes == fulano]
livrosEmprestados :: Database -> Pessoa -> [Livro]
livrosEmprestados db fulano = [liv | (pes, liv) <- db, pes == fulano]
--Letra a: Quantidade de livros emprestados deve ser menor ou igual que maxL, o numero maximo que alguem deve tomar emprestado
tomaEmprestado :: Database -> Pessoa -> Livro -> Database
tomaEmprestado db fulano titulo | ((numEmprestados db fulano) < maxL) = (fulano, titulo) : db
								| otherwise = db
--Funcao modificada para facilitar a devolucao do livro apenas pelo nome do livro
devolveLivro :: Database -> Pessoa -> Nome -> Database
devolveLivro ((p, (t,k,d)): r) f l
			|(p == f) && (t == l) = r
			| otherwise = (p,(t,k,d)) : devolveLivro r f l 
devolveLivro [ ] ful tit = error "Nao ha livro emprestado"
--Se livro ocorre no vetor de chaves retorna True. False Caso contrario.
occur :: Key -> Keys -> Bool
occur x (y:ys) | (x == y) = True
			 | otherwise = occur x ys
occur x [] = False
estaEmprestado :: Database -> Nome -> Bool
estaEmprestado db nome = (length [n | (_, (n, k, d)) <- db, n == nome]) > 0
--Letra b: Os livros podem ser encontrados atraves de palavras-chaves associadas a eles
buscarLivro :: Database -> Key -> [Livro]
buscarLivro db k = [(t,l,d) | (_, (t,l,d)) <- db, (occur k l)]
toDias :: Data -> Integer
toDias (d,m,a) = (d + (m*30) + (a*365))
devedores :: Database -> Data -> Nome -> [Pessoa]
devedores db atual l_name = [p | (p, (l,k,d)) <- db, (l == l_name), ((toDias atual) - (toDias d)) > maxD]
--Letra c: Livros atrasados podem ser encontrados
livrosAtrasados :: Database -> Data -> [Livro]
livrosAtrasados db atual = [(l,k,d) | (_, (l,k,d)) <- db, ((toDias atual) - (toDias d)) > maxD]
--Letra c: A lista de livros emprestados a uma determinada pessoa pode ser ordenada por data 
ordLivros :: [Livro] -> [Livro]
ordLivros ((pes, keys, dat):xs) = ((ordLivros [(p,k,d) | (p,k,d) <- xs, (toDias d) < (toDias dat)]) ++ [(pes, keys, dat)]) ++ (ordLivros [(p,k,d) | (p,k,d) <- xs, (toDias d) >= (toDias dat)])
ordLivros [] = []
livrosEmprestadosOrd :: Database -> Pessoa -> [Livro]
livrosEmprestadosOrd db p = ordLivros (livrosEmprestados db p)
-- maxL: Numero maximo de livros a serem emprestados
maxL :: Int
maxL = 3
-- maxD: Numero maximo de dias de um emprestimo
maxD :: Integer
maxD = 7
teste = [("Paulo", ("A Mente Nova do Rei", ["IA", "Roger Penrose", "Computador"], (12,6,2014))),
		("Ana", ("O Segredo de Luiza",["Empreendedorismo", "Fernando Dolabela"], (15, 5, 2014))),
		("Paulo", ("O Pequeno Principe", ["Antoine de Saint-Exupery", "Le Petit Prince", "historia"], (28, 6, 2014))), 
		("Mauro", ("O Capital", ["Karl Marx", "Das Kapital", "Socialismo"], (25, 6, 2014))),
		("Francisco", ("O Auto da Compadecida", ["Ariano Suassuna","Peça Teatral"], (22, 6, 2014))),
		("Paulo", ("O Cacador de Pipas", ["historia", "Khaled Hosseini", "Afeganistao"], (12,6,2014)))]
datual :: Data
datual = (30, 6, 2014)
oito.hs
occur :: String -> String -> String -> Bool
occur [] _ _ = True
occur x _ [] = True
occur _ [] _ = False
occur x (y:ys) (a:as) | y == a = occur x ys as
				 | otherwise = occur x (ys) x
getT :: Int -> (String, String) -> String
getT 0 (a,b) = a
getT 1 (a,b) = b
-- sep x y z b c
-- retorna uma tupla contendo as string anteriores e posteriores a string x na cadeia y
-- x: A string a ser encontrada
-- y: String onde deveremos buscar a String x
-- z: Restante dos caracteres de x a serem reconhecidos
-- b: Parte da String que coincidiu com o inicio de x, porem ainda esta em reconhecimento
-- c: Parte da String que foi lida mas que nao foi reconhecida
sep :: String -> String -> String -> String -> String -> (String, String)
sep [] y _ _ _= (y, [])
sep x y [] b c = (c, y)
sep _ [] _ b c = ((c++b), [])
sep x (y:ys) (a:as) b c | y == a = sep x ys as (b++[a]) c
				 		| otherwise = sep x ys x [] (c++b++[y])
substr :: String -> String -> String -> String
substr x y z | (occur x z x) = (getT 0 (sep x z x [] [])) ++ y ++ (getT 1 (sep x z x [] []))
		 | otherwise = z
{--
Para implementar o reconhecimento de strings, podemos simular um autômato que reconheça a substring1
na substring3 fazendo com que os estados do automato correspondam aos caracteres da substring1,
realizando a transicao dos caracteres um a um. Mantemos a string a ser reconhecida em memoria como 
o primeiro parâmetro da função occur e a cada passo fazemos uma chamada recursiva para a mesma, que 
equivale a uma transicao. O estado atual eh mantido na cabeca da lista correspondente ao terceiro 
parametro, juntamente com o restante a ser reconhecido. Quando não nos restam mais caracteres a 
serem reconhecidos(O terceiro parâmetro é a lista vazia), temos a certeza de que reconhecemos todos os 
caracteres e a substring1 pertence a substring3. Apos o reconhecimento, podemos realizar a 
substituicao com segurança. Em primeiro lugar separamos a string nas duas partes para a esquerda 
e para a direita da substring1, utilizando a função sep. Por ultimo, a funcao substr realiza o resto 
do trabalho concatenando a substring2 no meio das duas substrings resultantes de sep.
--}
quatro.hs
validAux :: Int -> Int -> [Int] -> Bool
validAux _ _ [] = True
validAux p c (x:xs) | p == x = False --rainhas na mesma linha
					| ((x-p) == c) || ((x-p) == (-c)) = False -- rainhas na mesma diagonal
					| otherwise = validAux p (c+1) xs
valid :: [Int] -> Bool
valid [] = True
valid (x:xs) = (validAux x 1 xs) && (valid xs)
--chess8Aux n
--resolve problema das 8 rainhas. O parametro n eh o numero de colunas restantes
chess8Aux :: Int -> [[Int]]
chess8Aux 0 = [[]]
chess8Aux 1 = [[1]]
chess8Aux n = filter valid [x:y | y <- (chess8Aux (n-1)), x <- [1 .. 8]]
chess8 :: [Int]
chess8 = (chess8Aux 8)!!1
{--
As funções valid e validAux são usadas com propósito de filtrar o espaço de configurações do tabuleiro 
de modo que as rainhas não conflitem em linha ou diagonal. A verificação por coluna não é necessária 
visto que é considerado que as rainhas são colocadas por padrão em colunas distintas, sendo o retorno 
de chess8 uma lista com as posições das linhas das rainhas em ordem de colunas. A função chess8Aux 
retorna um conjunto de soluções possíveis quando passada com o parâmetro 8, e a função chess retorna 
a solução de posição 1 na lista de listas retornada por chess8Aux.
--}
seis.hs
nove :: [Int]
nove = [4,1,4,2,1,2,1]
cinco :: [Int]
cinco = [4,2,3,2,4]
um :: [Int]
um = [0,2,1,2,1,2,1,2,1,2,1]
dois :: [Int]
dois = [3,2,5,2,3]
tres :: [Int]
tres = [3,2,4,2,4] 
quatro :: [Int]
quatro = [1,1,2,1,4,2,1,2,1]
seis :: [Int]
seis = [4,2,4,1,4]
sete :: [Int]
sete = [3,2,1,2,1,2,1,2,1]
oito
:: [Int]
oito = [4,1,5,1,4]
zero :: [Int]
zero = [4,1,2,1,2,1,4]
-- Letra a
toAst :: Int -> String
toAst 0 = ""
toAst n = "*"++(toAst (n-1))
toSpace :: Int -> String
toSpace 0 = ""
toSpace n = " "++(toSpace (n-1))
toString :: [Int] -> String
toString [] = ""
toString (x:[]) = toAst x
toString (x:y:ys) = (toAst x) ++ (toSpace y) ++ (toString ys)
--Letra b
type Linha = String
toLinhas :: String -> [Linha]
toLinhas [] = []
toLinhas (x:[]) = [[x]]
toLinhas (x:y:z:zs) = [x,y,z]:(toLinhas zs)
--Letra c
showLinhas :: [Linha] -> String
showLinhas [] = ""
showLinhas (x:xs) = x++"\n"++(showLinhas xs)
--Letra d
juntaLinhas :: [Linha] -> [Linha] -> [Linha]
juntaLinhas [] [] = []
juntaLinhas (x:xs) (y:ys) = (x++" "++y):(juntaLinhas xs ys)
--Letra e
ndig :: Int -> Int
ndig n | n < 10 = 1
 | n < 100 = 2
 | otherwise = 3
numeros :: [[Int]]
numeros = [zero,um,dois,tres,quatro,cinco,seis,sete,oito,nove]
tolcd :: Int -> String
tolcd n | (ndig n) == 1 = showLinhas (toLinhas (toString (numeros!!n)))
 | (ndig n) == 2 
 = showLinhas
 (juntaLinhas 
 (toLinhas (toString (numeros!!((mod n 100) `div` 10)))) 
 (toLinhas (toString (numeros!!(mod n 10))))
 )
 | (ndig n) == 3 
 = showLinhas
 (juntaLinhas 
 (juntaLinhas
 (toLinhas 
 (toString (numeros!!((mod n 1000) `div` 100)))) 
 (toLinhas 
 (toString (numeros!!((mod n 100) `div` 10)))) ) 
 (toLinhas (toString (numeros!!((mod n 10)))))
 )
--Letra f
type Estado = Bool
tcomp :: String -> Estado -> Int -> [Int]
tcomp [] False n | (n > 0) = [n]
 | otherwise = []
tcomp [] True n | (n > 0) = [n]
 | otherwise = []
tcomp (x:xs) True n | x == '*' = tcomp (xs) True (n+1)
 | otherwise = n:(tcomp (x:xs) False 0)
tcomp (x:xs) False n | x == ' ' = tcomp (xs) False (n+1)
 | otherwise = n:(tcomp (x:xs) True 0)
toCompact :: String -> [Int]
toCompact s = tcomp s True 0
sete.hs
pred_length :: Int -> [t] -> Bool
pred_length n x = (length x) >= n
list_sub :: [t] -> Int -> [[t]]
list_sub [] _ = [[]]
list_sub (x:xs) n | (length (x:xs)) >= n = filter (pred_length n) ([x:y | y <- (list_sub xs (n-1))] ++ (list_sub xs n) ) 
					| otherwise = [[]]
{--
Para retornar todas as sublistas de uma lista de elementos, tal que essas sublistas tenham um tamanho
maior ou igual que um número n eh necessário percorrer todo o espaço de busca. Recursivamente, podemos definir 
todas essas combinacoes em uma lista haskell do tipo (x:xs) como o conjunto de todas as sublistas de 
tamanho maiores ou iguais que n que nao contem a cabeça x unido ao conjunto das sublistas da concatenacao
da cabeça x a todas as sublistas possiveis de tamanho maior ou igual a n-1 na lista xs. A funcao filter garante a 
propriedade “>=n”, enquanto a condicao (length (x:xs)) >= n foi utilizada para fins de desempenho, podando 
onde as cadeias nao podem alcançar a longitude minima desejada.
--}
tres.hs
import Data.Matrix
my_sum :: (Num t) => [t] -> Int -> t
my_sum [] _ = 0
my_sum (x:xs) 1 = x + (my_sum xs (-1))
my_sum (x:xs) (-1) = (-1)*x + (my_sum xs 1)
my_minor :: (Num t) => Matrix t -> Int -> Matrix t
my_minor x a = minorMatrix 1 a x 
my_det :: (Num t) => Matrix t -> t
my_det x | (nrows x) == 2 = ((getElem 1 1 x)*(getElem 2 2 x) - (getElem 1 2 x)*(getElem 2 1 x))
		 | otherwise = (my_sum (map (my_det) (map (my_minor x) [1 .. (ncols x)])) 1)
mat :: Matrix Int
mat = fromList 3 3 [1..]
{--
Na implementação deste exercício foi utilizada a biblioteca Data.Matrix,
que pode ser instalada no linux com o utilitário cabal(apt-get install cabal-install) 
com o comando cabal install matrix.
Instrucoes de instalacao do cabal no windows podem ser encontradas em:
http://www.haskell.org/haskellwiki/Cabal-Install#Windows
Com a declaração de mat é possível realizar o teste da função my_det que recebe como 
argumento uma matriz de números e retorna o determinante dessa matriz, que no caso é zero. 
Foi utilizada a ideia recursiva de que o determinante de uma matriz é igual ao somatório 
do determinante multiplicado por um fator, que se alterna entre -1 e 1(função my_sum) das
submatrizes obtidas escolhendo-se uma linha e removendo, isoladamente, a coluna e o 
elemento de cada elemento desta linha até a coluna ncols x , onde x é uma matriz 
passada como parâmetro.
--}
um.hs
{--
A implementação deste item foi realizada utilizando uma função f2 auxiliar, 
que retorna a lista de elementos a ser concatenada baseada no vetor de posições, 
e a função utilitária map. A função map juntamente com a função implementada dec 
foi usada por conveniencia, para realizar a indexação dos elementos a partir de 
um, embora por default o operador !! use indexação baseada em zero. Adicionalmente
utilizamos a funcao reverse para imprimir os elementos extras na ordem especifica-
da.
--}
dec :: Int -> Int
dec x = x-1
f2 :: [Int] -> [t] -> [t]
f2 [] (y:ys) = []
f2 (x:xs) (y:ys) = ((y:ys)!!x):(f2 xs (y:ys))
f :: [Int] -> [t] -> [t]
f [] [] = []
f (x:xs) [] = []
f [] (y:ys) = (y:ys)
f (x:xs) (y:ys) = (y:ys)++(reverse(f2 (map (dec) (x:xs)) (y:ys)))
Haskell/lista 2/lista 2 respostas_Milton.pdf
Haskell – Lista 2
Aluno: Mílton Cézar Correia Segundo
Matrícula: 1075128
Disciplina: Programação Funcional
Professor: Francisco Vieira
Nota: Embora, as questões da lista de exercícios estejam descontínuadas(i. e. Da questão um se vá 
direto à questão 3), a ordem aqui colocada corresponde a ordem sequencial.
1. A implementação deste item foi realizada utilizando uma função f2 auxiliar, que retorna a lista de 
elementos a ser concatenada baseada no vetor de posições, e a função utilitária map. A função map 
juntamente com a função implementada dec foi usada por conveniencia, para realizar a indexação 
dos elementos a partir de um, embora por default o operador !! use indexação baseada em zero.
dec :: Int -> Int
dec x = x-1
f2 :: [Int] -> [t] -> [t]
f2 [] (y:ys) = []
f2 (x:xs) (y:ys) = ((y:ys)!!x):(f2 xs (y:ys))
f :: [Int] -> [t] -> [t]
f [] [] = []
f (x:xs) [] = []
f [] (y:ys) = (y:ys)
f (x:xs) (y:ys) = (y:ys)++(f2 (map (dec) (x:xs)) (y:ys))
Obs: O exemplo do enunciado está errado. Considerando-se que a função indexa os elementos da lista a partir do 
elemento 1 temos:
 f [2,1,4] ["a", "b", "c", "d"] = ["a", "b", "c", "d", "b", "a", "d"]
Pois os elementos [2, 1, 4] correspondem a “b”, “a”, e “d” da lista da esquerda, respectivamente. Ao contrário do que se 
apresenta no enunciado:
 f [2,1,4] ["a", "b", "c", "d"] = ["a", "b", "c", "d", "d", "a", "b"]
2. Na implementação deste exercício foi utilizada a biblioteca Data.Matrix que pode ser instalada 
no linux com o utilitário cabal(apt-get install cabal-install) com o comando cabal install matrix.
Segue o código:
import Data.Matrix
my_sum :: (Num t) => [t] -> Int -> t
my_sum [] _ = 0
my_sum (x:xs) 1 = x + (my_sum xs (-1))
my_sum (x:xs) (-1) = (-1)*x + (my_sum xs 1)
my_minor :: (Num t) => Matrix t -> Int -> Matrix t
my_minor x a = minorMatrix 1 a x 
my_det :: (Num t) => Matrix t -> t
my_det x | (nrows x) == 2 = ((getElem 1 1 x)*(getElem 2 2 x) - (getElem 1 2 x)*(getElem 2 1 
x))
 | otherwise = (my_sum (map (my_det) (map (my_minor x) [1 .. (ncols x)])) 1)
mat :: Matrix Int
mat = fromList 3 3 [1..]
Com a declaração de mat é possível realizar o teste da função my_det que recebe como argumento 
uma matriz de números e retorna o determinante dessa matriz, que no caso é zero. Foi utilizada a 
ideia recursiva de que o determinante de uma matriz é igual ao somatório do determinante 
multiplicado por um fator, que se alterna entre -1 e 1(função my_sum)
das submatrizes obtidas 
escolhendo-se uma linha e removendo, isoladamente, a coluna e o elemento de cada elemento desta 
linha até a coluna ncols x , onde x é uma matrix passada como parâmetro.
3. As funções valid e validAux são usadas com propósito de filtrar o espaço de configurações do 
tabuleiro de modo que as rainhas não conflitem em linha ou diagonal. A verificação por coluna não 
é necessária visto que é considerado que as rainhas são colocadas por padrão em colunas distintas, 
sendo o retorno de chess8 uma lista com as posições das linhas das rainhas em ordem de colunas. A 
função chess8Aux retorna um conjunto de soluções possíveis quando passada com o parâmetro 8, e 
a função chess retorna a solução de posição 1 na lista de listas retornada por chess8Aux.
validAux :: Int -> Int -> [Int] -> Bool
validAux _ _ [] = True
validAux p c (x:xs) | p == x = False --rainhas na mesma linha
| ((x-p) == c) || ((x-p) == (-c)) = False -- rainhas na mesma diagonal
| otherwise = validAux p (c+1) xs
valid :: [Int] -> Bool
valid [] = True
valid (x:xs) = (validAux x 1 xs) && (valid xs)
--chess8Aux n
--resolve problema das 8 rainhas. O parametro n eh o numero de colunas restantes
chess8Aux :: Int -> [[Int]]
chess8Aux 0 = [[]]
chess8Aux 1 = [[1]]
chess8Aux n = filter valid [x:y | y <- (chess8Aux (n-1)), x <- [1 .. 8]]
chess8 :: [Int]
chess8 = (chess8Aux 8)!!1
4. Neste apartado, utiliza-se uma função auxiliar com dois parâmetros auxiliares do tipo Bool e [[t]]. 
O primeiro serve para saber a qual lista o elemento pertence. Se o parâmetro Bool é verdadeiro 
então o elemento pertence à primeira lista e se é falso, assume-se que é da segunda lista.
f2 :: [t] -> Bool -> [[t]] -> [[t]]
f2 [] _ x = x
f2 (x:xs) True [a, b] = f2 xs False [a++[x], b]
f2 (x:xs) False [a, b] = f2 xs True [a, b++[x]]
f :: [t] -> [[t]]
f x = f2 x True [[], []]
5. 
a) Para converter a lista de inteiros em string utilizamos as funções auxiliares toAst e toSpace, que 
repetem astericos e espaços uma quantidade n de vezes.
toAst :: Int -> String
toAst 0 = ""
toAst n = "*"++(toAst (n-1))
toSpace :: Int -> String
toSpace 0 = ""
toSpace n = " "++(toSpace (n-1))
toString :: [Int] -> String
toString [] = ""
toString (x:[]) = toAst x
toString (x:y:ys) = (toAst x) ++ (toSpace y) ++ (toString ys)
b) Agrupa-se cada três digitos em uma lista
type Linha = String
toLinhas :: String -> [Linha]
toLinhas [] = []
toLinhas (x:[]) = [[x]]
toLinhas (x:y:z:zs) = [x,y,z]:(toLinhas zs)
c) Para cada elemento da lista se insere um '\n'.
showLinhas :: [Linha] -> String
showLinhas [] = ""
showLinhas (x:xs) = x++"\n"++(showLinhas xs)
d) 
juntaLinhas :: [Linha] -> [Linha] -> [Linha]
juntaLinhas [] [] = []
juntaLinhas (x:xs) (y:ys) = (x++" "++y):(juntaLinhas xs ys)
e) Para esta implementação foi utilizada uma função ndig como função de apoio para definir as 
ações específicas para números de 1, 2 e 3 digítos. Para números de 1 dígito basta utilizar a recursão 
showLinhas → toLinhas → toString. Para números de mais de um dígito devemos concatenar o 
resultado de toLinhas de cada dígito, de tal forma que a possamos posicionar o \n ao final de cada 
linha i corretamente. Para tal utilizamos a função que contruímos juntaLinhas.
ndig :: Int -> Int
ndig n | n < 10 = 1
 | n < 100 = 2
 | otherwise = 3
numeros :: [[Int]]
numeros = [zero,um,dois,tres,quatro,cinco,seis,sete,oito,nove]
tolcd :: Int -> String
tolcd n | (ndig n) == 1 = showLinhas (toLinhas (toString (numeros!!n)))
 | (ndig n) == 2 
 = showLinhas
 (juntaLinhas 
 (toLinhas (toString (numeros!!((mod n 100) `div` 10)))) 
 (toLinhas (toString (numeros!!(mod n 10))))
 )
 | (ndig n) == 3 
 = showLinhas
 (juntaLinhas 
 (juntaLinhas
 (toLinhas 
 (toString (numeros!!((mod n 1000) `div` 100)))) 
 (toLinhas 
 (toString (numeros!!((mod n 100) `div` 10)))) ) 
 (toLinhas (toString (numeros!!((mod n 10)))))
 )
f)
type Estado = Bool
tcomp :: String -> Estado -> Int -> [Int]
tcomp [] False n | (n > 0) = [n]
 | otherwise = []
tcomp [] True n | (n > 0) = [n]
 | otherwise = []
tcomp (x:xs) True n | x == '*' = tcomp (xs) True (n+1)
 | otherwise = n:(tcomp (x:xs) False 0)
tcomp (x:xs) False n | x == ' ' = tcomp (xs) False (n+1)
 | otherwise = n:(tcomp (x:xs) True 0)
toCompact :: String -> [Int]
toCompact s = tcomp s True 0
A implementação da função toCompact é passada à função auxiliar tcomp que acrescenta dois 
parâmetros. Um deles é uma flag Boolean. O valor True indica que a função está contabilizando 
asteriscos e o valor falso indica que a função está contabilizando espaços em brancos. O outro 
parâmetro é um inteiro n, que indica a quantidade do caractér atual sendo lida
6. Para retornar todas as permutações de uma lista de elementos, tal que essas permutações tenham 
um tamanho maior ou igual que um número n é necessário percorrer todo o espaço de busca. 
Recursivamente, podemos definir todas essas permutações em uma lista haskell do tipo (x:xs), 
como o conjunto de todas as permutações de tamanho maiores ou iguais que n que não contém a 
cabeça x unido ao conjunto da concatenação da cabeça x a todas as permutações possíveis de 
tamanho n-1 na lista xs. A função filter garante a propriedade “>=n”, enquanto a condição (length 
(x:xs)) >= n foi utilizada para fins de desempenho, podando onde as cadeias não podem alcançar a 
longitude mínima desejada.
pred_length :: Int -> [t] -> Bool
pred_length n x = (length x) >= n
list_perms :: [t] -> Int -> [[t]]
list_perms [] _ = [[]]
list_perms (x:xs) n | (length (x:xs)) >= n 
 = filter (pred_length n) ([x:y | y <- (list_perms xs (n-1))] ++ (list_perms xs n) ) 
 | otherwise = [[]]
7. Para implementar o reconhecimento de strings, podemos simular um autômato que reconheça a 
substring1 na substring3 fazendo com que os estados do autômato correspondam aos caracteres da 
substring1, realizando a transição dos caracteres um a um. Mantemos a string a ser reconhecida em 
memória como o primeiro parâmetro da função occur e a cada passo fazemos uma chamada 
recursiva à mesma, que equivale a um movimento na fita. A primeira posição do cabeçote é mantida 
no terceiro parâmetro, juntamente com o restante a ser reconhecido. Quando não nos restam mais 
caracteres a serem reconhecidos(O terceiro parâmetro é a lista vazia), temos a certeza de que 
reconhecemos todos os caracteres e a substring1 pertence a substring3. Após o reconhecimento, 
podemos realizar a substituição com segurança. Em primeiro lugar separamos a string nas duas 
partes à esquerda e à direita da substring1, utilizando a função sep. Por último, a função substr 
realiza o resto do trabalho concatenando a substring2 no meio das duas substrings resultantes de 
sep.
 
occur :: String -> String -> String -> Bool
occur [] _ _ = True
occur x _ [] = True
occur _ [] _ = False
occur x (y:ys) (a:as) | y == a = occur x ys as
 | otherwise = occur x (ys) x
getT :: Int -> (String, String) -> String
getT 0 (a,b) = a
getT 1 (a,b) = b
-- sep x y z b c
-- retorna uma tupla contendo as string anteriores e posteriores a string x na cadeia y
-- x: A string a ser encontrada
-- y: String onde deveremos buscar a String x
-- z: Restante dos caracteres de x a serem reconhecidos
-- b: Parte da String que coincidiu com o inicio de x, porem ainda esta em reconhecimento
-- c: Parte da String que foi lida mas que nao foi reconhecida
sep :: String -> String -> String -> String -> String -> (String, String)
sep [] y _ _ _= (y, [])
sep x y [] b c = (c, y)
sep _ [] _ b c = ((c++b),
[])
sep x (y:ys) (a:as) b c | y == a = sep x ys as (b++[a]) c
 | otherwise = sep x ys x [] (c++b++[y])
substr :: String -> String -> String -> String
substr x y z | (occur x z x) = (getT 0 (sep x z x [] [])) ++ y ++ (getT 1 (sep x z x [] 
[]))
 | otherwise = z
8. Onde está o banco de dados ao qual a questão se refere?
9. Todas as permutações possíveis da lista (x:xs) são todas as permutações de (xs) e todas as 
concatenações de x com cada uma das cadeias do conjunto de permutações de xs.
perms :: [t] -> [[t]]
perms [] = [[]]
perms (x:xs) = [x:y | y <- (perms xs)] ++ (perms xs)
Haskell/lista 2/lista 2 respostas_Milton.odt
Haskell – Lista 2
Aluno: Mílton Cézar Correia Segundo
Matrícula: 1075128
Disciplina: Programação Funcional
Professor: Francisco Vieira
Nota: Embora, as questões da lista de exercícios estejam descontínuadas(i. e. Da questão um se vá direto à questão 3), a ordem aqui colocada corresponde a ordem sequencial.
1. A implementação deste item foi realizada utilizando uma função f2 auxiliar, que retorna a lista de elementos a ser concatenada baseada no vetor de posições, e a função utilitária map. A função map juntamente com a função implementada dec foi usada por conveniencia, para realizar a indexação dos elementos a partir de um, embora por default o operador !! use indexação baseada em zero.
dec :: Int -> Int
dec x = x-1
f2 :: [Int] -> [t] -> [t]
f2 [] (y:ys) = []
f2 (x:xs) (y:ys) = ((y:ys)!!x):(f2 xs (y:ys))
f :: [Int] -> [t] -> [t]
f [] [] = []
f (x:xs) [] = []
f [] (y:ys) = (y:ys)
f (x:xs) (y:ys) = (y:ys)++(reverse (f2 (map (dec) (x:xs)) (y:ys)))
2. Na implementação deste exercício foi utilizada a biblioteca Data.Matrix que pode ser instalada no linux com o utilitário cabal(apt-get install cabal-install) com o comando cabal install matrix.
Segue o código:
import Data.Matrix
my_sum :: (Num t) => [t] -> Int -> t
my_sum [] _ = 0
my_sum (x:xs) 1 = x + (my_sum xs (-1))
my_sum (x:xs) (-1) = (-1)*x + (my_sum xs 1)
my_minor :: (Num t) => Matrix t -> Int -> Matrix t
my_minor x a = minorMatrix 1 a x 
my_det :: (Num t) => Matrix t -> t
my_det x | (nrows x) == 2 = ((getElem 1 1 x)*(getElem 2 2 x) - (getElem 1 2 x)*(getElem 2 1 x))
		 | otherwise = (my_sum (map (my_det) (map (my_minor x) [1 .. (ncols x)])) 1)
mat :: Matrix Int
mat = fromList 3 3 [1..]
Com a declaração de mat é possível realizar o teste da função my_det que recebe como argumento uma matriz de números e retorna o determinante dessa matriz, que no caso é zero. Foi utilizada a ideia recursiva de que o determinante de uma matriz é igual ao somatório do determinante multiplicado por um fator, que se alterna entre -1 e 1(função my_sum) das submatrizes obtidas escolhendo-se uma linha e removendo, isoladamente, a coluna e o elemento de cada elemento desta linha até a coluna ncols x , onde x é uma matrix passada como parâmetro.
3. As funções valid e validAux são usadas com propósito de filtrar o espaço de configurações do tabuleiro de modo que as rainhas não conflitem em linha ou diagonal. A verificação por coluna não é necessária visto que é considerado que as rainhas são colocadas por padrão em colunas distintas, sendo o retorno de chess8 uma lista com as posições das linhas das rainhas em ordem de colunas. A função chess8Aux retorna um conjunto de soluções possíveis quando passada com o parâmetro 8, e a função chess retorna a solução de posição 1 na lista de listas retornada por chess8Aux.
validAux :: Int -> Int -> [Int] -> Bool
validAux _ _ [] = True
validAux p c (x:xs) | p == x = False --rainhas na mesma linha
			| ((x-p) == c) || ((x-p) == (-c)) = False -- rainhas na mesma diagonal
			| otherwise = validAux p (c+1) xs
valid :: [Int] -> Bool
valid [] = True
valid (x:xs) = (validAux x 1 xs) && (valid xs)
--chess8Aux n
--resolve problema das 8 rainhas. O parametro n eh o numero de colunas restantes
chess8Aux :: Int -> [[Int]]
chess8Aux 0 = [[]]
chess8Aux 1 = [[1]]
chess8Aux n = filter valid [x:y | y <- (chess8Aux (n-1)), x <- [1 .. 8]]
chess8 :: [Int]
chess8 = (chess8Aux 8)!!1
4. Neste apartado, utiliza-se uma função auxiliar com dois parâmetros auxiliares do tipo Bool e [[t]]. O primeiro serve para saber a qual lista o elemento pertence. Se o parâmetro Bool é verdadeiro então o elemento pertence à primeira lista e se é falso, assume-se que é da segunda lista.
f2 :: [t] -> Bool -> [[t]] -> [[t]]
f2 [] _ x = x
f2 (x:xs) True [a, b] = f2 xs False [a++[x], b]
f2 (x:xs) False [a, b] = f2 xs True [a, b++[x]]
f :: [t] -> [[t]]
f x = f2 x True [[], []]
5. 
a) Para converter a lista de inteiros em string utilizamos as funções auxiliares toAst e toSpace, que repetem astericos e espaços uma quantidade n de vezes.
toAst :: Int -> String
toAst 0 = ""
toAst n = "*"++(toAst (n-1))
toSpace :: Int -> String
toSpace 0 = ""
toSpace n = " "++(toSpace (n-1))
toString :: [Int] -> String
toString [] = ""
toString (x:[]) = toAst x
toString (x:y:ys) = (toAst x) ++ (toSpace y) ++ (toString ys)
b) Agrupa-se cada três digitos em uma lista
type Linha = String
toLinhas :: String -> [Linha]
toLinhas [] = []
toLinhas (x:[]) = [[x]]
toLinhas (x:y:z:zs) = [x,y,z]:(toLinhas zs)
c) Para cada elemento da lista se insere um '\n'.
showLinhas :: [Linha] -> String
showLinhas [] = ""
showLinhas (x:xs) = x++"\n"++(showLinhas xs)
d) 
juntaLinhas :: [Linha] -> [Linha] -> [Linha]
juntaLinhas [] [] = []
juntaLinhas (x:xs) (y:ys) = (x++" "++y):(juntaLinhas xs ys)
e) Para esta implementação foi utilizada uma função ndig como função de apoio para definir as ações específicas para números de 1, 2 e 3 digítos. Para números de 1 dígito basta utilizar a recursão showLinhas → toLinhas → toString. Para números de mais de um dígito devemos concatenar o resultado de toLinhas de cada dígito, de tal forma que a possamos posicionar o \n ao final de cada linha i corretamente. Para tal utilizamos a função que contruímos juntaLinhas.
ndig :: Int -> Int
ndig n | n < 10 = 1
| n < 100 = 2
| otherwise = 3
numeros :: [[Int]]
numeros = [zero,um,dois,tres,quatro,cinco,seis,sete,oito,nove]
tolcd :: Int -> String
tolcd n | (ndig n) == 1 = showLinhas (toLinhas (toString (numeros!!n)))
| (ndig n) == 2 
= showLinhas
(juntaLinhas 
(toLinhas (toString (numeros!!((mod n 100) `div` 10)))) 
(toLinhas (toString (numeros!!(mod n 10))))
)
| (ndig n) == 3 
= showLinhas
(juntaLinhas 
(juntaLinhas
(toLinhas 
(toString (numeros!!((mod n 1000) `div` 100)))) 
(toLinhas 
(toString (numeros!!((mod n 100) `div` 10)))) ) 
(toLinhas (toString (numeros!!((mod n 10)))))
)
f)
type Estado = Bool
tcomp :: String -> Estado -> Int -> [Int]
tcomp [] False n | (n > 0) = [n]
| otherwise = []
tcomp [] True n | (n > 0) = [n]
| otherwise = []
tcomp (x:xs) True n | x == '*' = tcomp (xs) True (n+1)
| otherwise = n:(tcomp (x:xs) False 0)
tcomp (x:xs) False n | x == ' ' = tcomp (xs) False (n+1)
| otherwise = n:(tcomp (x:xs) True 0)
toCompact :: String -> [Int]
toCompact s = tcomp s True 0
A implementação da função toCompact é passada à função auxiliar tcomp que acrescenta dois parâmetros. Um deles é uma flag Boolean. O valor True indica que a função está contabilizando asteriscos e o valor falso indica que a função está contabilizando espaços em brancos. O outro parâmetro é um inteiro n, que indica a quantidade do caractér atual sendo lida
6. Para retornar todas as permutações de uma lista de elementos, tal que essas permutações tenham um tamanho maior ou igual que um número n é necessário percorrer todo o espaço de busca. Recursivamente,
podemos definir todas essas permutações em uma lista haskell do tipo (x:xs), como o conjunto de todas as permutações de tamanho maiores ou iguais que n que não contém a cabeça x unido ao conjunto da concatenação da cabeça x a todas as permutações possíveis de tamanho n-1 na lista xs. A função filter garante a propriedade “>=n”, enquanto a condição (length (x:xs)) >= n foi utilizada para fins de desempenho, podando onde as cadeias não podem alcançar a longitude mínima desejada.
pred_length :: Int -> [t] -> Bool
pred_length n x = (length x) >= n
list_perms :: [t] -> Int -> [[t]]
list_perms [] _ = [[]]
list_perms (x:xs) n | (length (x:xs)) >= n 
	 = filter (pred_length n) ([x:y | y <- (list_perms xs (n-1))] ++ (list_perms xs n) ) 
	 | otherwise = [[]]
7. Para implementar o reconhecimento de strings, podemos simular um autômato que reconheça a substring1 na substring3 fazendo com que os estados do autômato correspondam aos caracteres da substring1, realizando a transição dos caracteres um a um. Mantemos a string a ser reconhecida em memória como o primeiro parâmetro da função occur e a cada passo fazemos uma chamada recursiva à mesma, que equivale a um movimento na fita. A primeira posição do cabeçote é mantida no terceiro parâmetro, juntamente com o restante a ser reconhecido. Quando não nos restam mais caracteres a serem reconhecidos(O terceiro parâmetro é a lista vazia), temos a certeza de que reconhecemos todos os caracteres e a substring1 pertence a substring3. Após o reconhecimento, podemos realizar a substituição com segurança. Em primeiro lugar separamos a string nas duas partes à esquerda e à direita da substring1, utilizando a função sep. Por último, a função substr realiza o resto do trabalho concatenando a substring2 no meio das duas substrings resultantes de sep.
occur :: String -> String -> String -> Bool
occur [] _ _ = True
occur x _ [] = True
occur _ [] _ = False
occur x (y:ys) (a:as) | y == a = occur x ys as
				 | otherwise = occur x (ys) x
getT :: Int -> (String, String) -> String
getT 0 (a,b) = a
getT 1 (a,b) = b
-- sep x y z b c
-- retorna uma tupla contendo as string anteriores e posteriores a string x na cadeia y
-- x: A string a ser encontrada
-- y: String onde deveremos buscar a String x
-- z: Restante dos caracteres de x a serem reconhecidos
-- b: Parte da String que coincidiu com o inicio de x, porem ainda esta em reconhecimento
-- c: Parte da String que foi lida mas que nao foi reconhecida
sep :: String -> String -> String -> String -> String -> (String, String)
sep [] y _ _ _= (y, [])
sep x y [] b c = (c, y)
sep _ [] _ b c = ((c++b), [])
sep x (y:ys) (a:as) b c | y == a = sep x ys as (b++[a]) c
				 		| otherwise = sep x ys x [] (c++b++[y])
substr :: String -> String -> String -> String
substr x y z | (occur x z x) = (getT 0 (sep x z x [] [])) ++ y ++ (getT 1 (sep x z x [] []))
		 | otherwise = z
8. Onde está o banco de dados ao qual a questão se refere?
9. O conjunto de todas as sublistas e subsequencias possíveis da lista (x:xs) é a união entre o conjunto de todas as sublistas de (xs) e o conjunto de todas as concatenações [x]++y, tal que y pertence ao conjunto de todas as sublistas e subsequencias de xs.
perms :: [t] -> [[t]]
perms [] = [[]]
perms (x:xs) = [x:y | y <- (perms xs)] ++ (perms xs)
Haskell/lista 2/dez.hs
sub_lists :: [t] -> [[t]]
sub_lists [] = [[]]
sub_lists (x:xs) = [x:y | y <- (sub_lists xs)] ++ (sub_lists xs)
{--
O conjunto de todas as sublistas e subsequencias possiveis da lista (x:xs)
eh a uniao entre o conjunto de todas as sublistas de (xs) e o conjunto de 
todas as concatenacoes [x]++y, tal que y pertence ao conjunto de todas as
sublistas e subsequencias de xs.
--}
Haskell/lista 2/cinco.hs
f2 :: [t] -> Bool -> [[t]] -> [[t]]
f2 [] _ x = x
f2 (x:xs) True [a, b] = f2 xs False [a++[x], b]
f2 (x:xs) False [a, b] = f2 xs True [a, b++[x]]
f :: [t] -> [[t]]
f x = f2 x True [[], []]
{--
As funções valid e validAux são usadas com propósito de filtrar o espaço de configurações 
do tabuleiro de modo que as rainhas não conflitem em linha ou diagonal. A verificação por 
coluna não é necessária visto que é considerado que as rainhas são colocadas por padrão 
em colunas distintas, sendo o retorno de chess8 uma lista com as posições das linhas das 
rainhas em ordem consecutiva de colunas. A função chess8Aux retorna um conjunto de soluções possíveis
quando passada com o parâmetro 8, e a função chess retorna a solução de posição 1 na lista
de listas retornada por chess8Aux.
--}
Haskell/lista 2/Lista_2_12014.docx
Universidade Federal do Piauí
Centro de Ciências da Natureza
Departamento de Computação
Disciplina: Linguagens Funcionais
Professor: Francisco Vieira de Souza
2ª. Lista de exercícios (para o dia 1º de julho de 2014)
Defina, em Haskell uma função "f" que, dadas uma lista "i" de inteiros e uma outra lista "l" qualquer, retorne uma nova lista constituída por "l" seguida de seus elementos que têm posição indicada em "i",conforme o exemplo a seguir: 
 f [2,1,4] ["a", "b", "c", "d"] = ["a", "b", "c", "d", "d", "a", "b"]
2. Defina, em Haskell, uma função que calcula o Determinante de uma matriz quadrada de ordem “n".
3. Resolva o problema das oito rainhas, usando Haskell.
4. Defina, em Haskell, uma função “f" que, dada uma lista “l", construa duas outras listas “l1" e “l2" de 
 forma que “l1" contenha os elementos de “l" de posição ímpar e “l2" contenha os elementos de “l" de 
 posição par, preservando a posição relativa dos elementos, conforme os exemplos a seguir: 
 f [a, b, c, d] = [[a, c], [b, d]] 
 f [a, b, c, d, e] = [[a, c, e],[b, d]]
5. Um pequeno visor de cristal liquido (LCD) contém uma matriz 5x3 que pode mostrar um número, como 9 ou 5. Por exemplo:
 *** ***
 * * *
 *** ***
 * *
 * ***
 O formato de cada número é definido por uma lista de inteiros que indica quantos '*' se repetem, 
 seguidos de quantos brancos se repetem, até o final da matriz 5x3, começando da primeira linha até a 
 última:
 nove,cinco,um,dois,tres,quatro,seis,sete,oito,zer :: [Int]
 nove = [4,1,4,2,1,2,1]
 cinco = [4,2,3,2,4]
 um = [0,2,1,2,1,2,1,2,1,2,1]
 dois = [3,2,5,2,3]
 tres = [3,2,4,2,4] 
 quatro = [1,1,2,1,4,2,1,2,1]
 seis = [4,2,4,1,4]
 sete = [3,2,1,2,1,2,1,2,1]
 oito = [4,1,5,1,4]
 zero = [4,1,2,1,2,1,4]
 indicando que o número nove é composto por 4 '*'s (três na primeira linha e um na segunda), seguido de 1 espaço, mais 4 '*'s, 2 espaços, 1 '*', 2 espaços e 1 '*'). Faça funções para:
 
Dado o formato do número (lista de inteiros) gerar a String correspondente de '*' e espaços.
 toString :: [Int] -> String
 toString nove ==> "**** **** * *"
Faça uma função que transforme a String de '*'s e espaços em uma lista de Strings, cada uma representando uma linha do LCD: 
 type Linha = String
 toLinhas :: String -> [Linha]
 toLinhas "**** **** * *" ==> ["***","* *","***"," *"," *"]
Faça uma função que pegue uma lista de Strings e a transforme em uma única String com '\n' entre cada uma delas:
 showLinhas :: [Linha] -> String
 showLinhas ["***","* *","***"," *"," *"] = "***\n* *\n***\n *\n *"
Faça uma função que pegue duas listas de linhas e transforme-as em uma única lista de linhas, onde as linhas originais se tornam uma única, com um espaço entre elas:
 juntaLinhas :: [Linha] -> [Linha] -> [Linha]
 juntaLinhas ["***","* *","***"," *"," *"] ["***","* *","***","

Teste o Premium para desbloquear

Aproveite todos os benefícios por 3 dias sem pagar! 😉
Já tem cadastro?

Continue navegando