Vem com uma GUI "a la" linha de comando, com algumas características como possibilitar codificações em "100% pure Python" (Referência) e ser cross-plataform (Windows e Linux).
Poderosa IDE para Python. Pena ser sem versões nativas para Linux e Mac OS.
Optei por utilizar o Eclipse como minha IDE. Assim sendo, a instalação do GHC atrelado ao Eclipse foi bastante similar para os diferentes Sistemas Operacionais. Salvo pequenos detalhes.
Basicamente, instala-se o Eclipse, o GHC e, após isso, dentro do Eclipse procede-se da seguinte maneira:
Configurando o GHC no Eclipse:
Acessando a página de download do SWI-Prolog, basta selecionar para qual sistema operacional deseja-se baixar uma versão estável e seguir procedimentos padrões de instalação (para qualquer SO). Tanto a instalação quanto o uso do SWI-PL é bastante "straight-forward".
Clique aqui para ver a página com os enunciados! -- Verifica se o numero inteiro eh par ou impar par :: Int -> Bool par x | mod x 2 == 0 = True | otherwise = False -- Head que retornar o quadrado do primeiro elemento de uma lista potHead :: [Int] -> Int potHead x = (head x)^2 -- Recebe a nota como argumento e retorna o conceito correspondente conceito :: Float -> Char conceito nota | nota >= 9.0 = 'A' | nota >= 7.5 && nota < 9.0 = 'B' | nota >= 6.0 && nota < 7.5 = 'C' | nota >= 4.0 && nota < 6.0 = 'D' | nota < 4.0 = 'E' -- Calcula o somatorio de elementos de uma lista usando recursividade somaElem :: [Int] -> Int somaElem [] = 0 somaElem lis = (head lis) + somaElem (tail lis)
Clique aqui para ver a página com os enunciados! module NomeDoArquivo where -- Importe feito para uso da funcao "toUpper" import Char -- Funcao reescrita usando guardas ("|") e o operador mod de forma infixa -- test1 a b = -- if mod b 3 == 0 then a + b -- else if mod b 5 == 0 then b - a -- else a test1 a b | b `mod` 3 == 0 = a + b | b `mod` 5 == 0 = b - a | otherwise = a -- Esta funcao calcula a soma dos N primeiros elementos de uma lista somaN :: Int -> [Int] -> Int somaN _ [] = 0 somaN 0 _ = 0 somaN n (x:xs) = x + somaN (n-1) xs -- Mesma funcao que acima, porem, sem recursao somaM :: Int -> [Int] -> Int somaM _ [] = 0 somaM 0 _ = 0 somaM n (x:xs) = x + foldr1 (+) (take (n-1) xs) -- Ou simplesmente (dica da Professora Andrea) somaM n lis = sum (take n lis) -- Calcula a raiz de cada elemento da lista e o soma com 5 -- Obs.: radFive :: [Int] -> [Int] nao funciona, pois, sqrt -- retorna valores do tipo Double radFive :: [Double] -> [Double] radFive [] = [] radFive (x:xs) = (sqrt x) + 5 : radFive xs -- Testando a funcao map -- Teste 1: --radFive :: [Double] -> [Double] --radFive [] = [] --radFive (x:xs) = sqrt x : map sqrt xs -- Teste 2: --radFive :: (a -> b) -> [a] -> [b] --radFive f [] = [] --radFive f (x:xs) = f x : map f xs -- Exemplo da internet da funcao zip zipp :: [t] -> [u] -> [(t,u)] zipp (a:as) (b:bs) = (a,b):zipp as bs zipp [] [] = [] -- Abaixo estah uma funcao que eleva ao cubo cada elemento da lista pot3rec :: [Int] -> [Int] pot3rec [] = [] pot3rec (x:xs) = x^3 : pot3rec xs -- a mesma funcao acima, porem, sem recursao e usando funcao de alta ordem pot3 :: [Int] -> [Int] pot3 [] = [] pot3 (x:xs) = x^3 : map (^3) xs -- Funcao sem recursao que adiciona sufixo as strings contidas -- em uma lista. Exemplo: addSuffix "@inf.ufsm.br" ["fulano", "beltrano"] -- deve retornar a seguinte lista: ["fulano@inf.ufsm.br", "beltrano@inf.ufsm.br"]] addSuffix :: String -> [String] -> [String] addSuffix _ [] = [] addSuffix s lista = map (++ s) lista -- Funcao que recebe uma lista e retorna outra lista -- contendo apenas os numeros impares da recebida --selectOdd :: [Int] -> [Int] --selectOdd [] = [] --selectOdd lista = filter (odd) lista -- mesma funcao acima, porem, agora, com recursao selectOdd :: [Int] -> [Int] selectOdd [] = [] selectOdd (x:xs) | x `mod` 2 /= 0 = x : selectOdd xs | otherwise = selectOdd xs -- Funcao nao recursiva que retorna uma lista com os -- n primeiros numeros pares nPares :: Int -> [Int] -> [Int] nPares 0 [] = [] nPares _ [] = [] nPares n lista = take n (filter (even) lista) -- ENTRADA/SAIDA --main = putStr "Ola Mundo!" --main = putStr "Ola Mundo!\n" --main = putStrLn "Ola Mundo!" -- as diferencas entre os dois itens comentados nao existem; -- o que existe eh uma diferenca entre ambos e o primeiro main --main = do -- putStr "Digite seu nome: " -- nome < - getLine -- detalhe: não existe o espaco entre < e - -- putStrLn ("Ola " ++ nome) -- funcao acima alterada para mostrar o nome com a -- primeira letra em maiuscula main = do putStr "Digite seu nome com a primeira letra maiuscula: " -- haha :) nome < - getLine -- detalhe: não existe o espaco entre < e - putStrLn ("Ola " ++ maiusc nome) -- maiusc :: String -> String maiusc (x:xs) = toUpper x : xs
Clique aqui para ver a página com os enunciados! % Arquivo bd.pl % Exemplo de programa em Prolog que define % fatos e regras sobre pessoas e localizacoes geograficas. nasceu_em(andre, santa_maria). nasceu_em(jose, salvador). nasceu_em(joana, salvador). nasceu_em(marc, paris). nasceu_em(michel, paris). nasceu_em(maria, porto_alegre). nasceu_em(X, rio_grande_do_sul) :- nasceu_em(X, santa_maria). nasceu_em(X, rio_grande_do_sul) :- nasceu_em(X, porto_alegre). nasceu_em(X, bahia) :- nasceu_em(X, salvador). nasceu_em(X, franca) :- nasceu_em(X, paris). nasceu_em(X, europa) :- nasceu_em(X, franca). nasceu_em(X, brasil) :- nasceu_em(X, bahia). nasceu_em(X, brasil) :- nasceu_em(X, rio_grande_do_sul). idade(andre, 25). idade(jose, 30). idade(joana, 22). idade(marc, 28). idade(michel, 40). idade(maria, 32). gaucho(X) :- nasceu_em(X, rio_grande_do_sul). brasileiro(X) :- nasceu_em(X, brasil). europeu(X) :- nasceu_em(X, europa). Fatos, regras e consultas 1. Examine o programa bd.pl e identifique quais são os fatos e quais são as regras neste arquivo. Neste caso, todos que possuem a expressão ":-" são "Regras"; os demais, "Fatos". 2. Observe as regras neste programa. O que elas permitem deduzir? Utilizando como exemplo a regra "nasceu_em(X, rio_grande_do_sul) (...)", deduz-se que, quem nasceu em santa_maria e porto_alegre nasceu no rio_grande_do_sul. 3. Verifique qual será a resposta à seguinte consulta: ?- europeu(jose). false. 4. Verifique qual será a resposta à seguinte consulta: ?- gaucho(andre). true . Tecle "Enter" ou "." após a primeira resposta, para evitar que se procurem outras. 5. Verifique quais serão as respostas para a seguinte consulta (tecle ";" após cada resposta para descobrir se existem outras): ?- brasileiro(X). % "Quem é brasileiro?" X = jose ; X = joana ; X = andre ; X = maria ; false. OBS.: após cada resposta, pressiona-se ";" para a obtenção de outras possíveis respostas (caso hajam) ou "." para finalizar a busca. 6. Transforme as seguintes afirmações em fatos Prolog e inclua-os em bd.pl (recarregue o programa modificado!): "Joana nasceu em Salvador." "Joana tem 22 anos." "Michel nasceu em Paris e tem 40 anos." Ver o exemplo de programa expresso no início destes exercícios. 7. Considerando a base de dados em bd.pl, transforme as seguintes perguntas em consultas Prolog (verifique quais são as respostas retornadas pelo sistema): a) "José nasceu no Brasil?" b) "Quais são as pessoas nascidas na Europa?" c) "Quais são as pessoas com mais de 30 anos?" d) "Quem são os brasileiros com menos de 30 anos?" a) nasceu_em(jose,brasil). true. b) nasceu_em(X, europa). X = marc ; X = michel ; false. c) idade(X, Y), Y > 30. X = michel, Y = 40 ; X = maria, Y = 32. d) nasceu_em(X, brasil), idade(X, Y), Y < 30. X = joana, Y = 22 ; X = andre, Y = 25. ; false. Listas 1. Quais serão os resultados das seguintes consultas com unificação? ?- [1,2,3,4] = [H|T]. H = 1, T = [2, 3, 4]. ?- [] = [H|T]. false. ?- [1] = [H|T]. H = 1, T = []. ?- [1,2,3,4] = [_|T]. T = [2, 3, 4]. ?- [1,2,3,4] = [H|_]. H = 1. ?- [[1,2],[3,4]] = [H|T]. H = [1,2], T = [[3,4]]. 2. Inclua o seguinte código Prolog no programa bd.pl: sumlist([],0). sumlist([H|T], S) :- sumlist(T, S1), S is H + S1. O predicado sumlist serve para determinar o somatório dos elementos de uma lista. O caso base é um fato que indica que o somatório de elementos de uma lista vazia é 0. O caso geral é uma regra que aplica o predicado recursivamente ao restante (tail) da lista. Outra forma menos abreviada de escrever o caso geral é: sumlist(L, S) :- L = [H|T], sumlist(T, S1), S is H + S1. 3. Considerando a explicação acima, qual será o resultado da seguinte consulta? ?- sumlist([4,5],S). S = 9. 4. Use o predicado trace para rastrear a execução desta consulta em Prolog: ?- trace. [trace] ?- sumlist([4,5],S). Tecle Enter a cada etapa para prosseguir. Ao final, use o predicado nodebug para encerrar o rastreio: [trace] ?- nodebug. 5. O predicado member está definido em Prolog e serve para verificar se um dado elemento pertence a uma lista. Teste esse predicado conforme o exemplo abaixo: ?- member(5, [1,6,4]). false. ?- member(6, [1,6,4]). true. 6. Crie um predicado "pertence" que funcione como o predicado member, ou seja, que verifique se um dado elemento pertence à lista dada. Esse predicado deverá ser recursivo, sendo que o caso base da recursão será quando o elemento E for o primeiro elemento (head) da lista. O caso geral deverá apenas aplicar o predicado ao restante (tail) da lista. pertence(X,[X|_]). pertence(X,[_|S]) :- pertence(X,S).
Clique aqui para ver a página com os enunciados! Fatos, Regras e Consultas 1. Crie um arquivo de programa com extensão .pl e preencha-o com os seguintes fatos Prolog: % Filmes: filme(id_filme, nome_filme) filme(1, 'Monty Python'). filme(2, 'O Senhor dos Aneis'). filme(3, 'Gattaca'). % Numero de locacoes de cada filme: % locacoes(id _filme, num_locacoes) locacoes(1, 500). locacoes(2, 1000). locacoes(3, 100). 2. Considerando a base do exercício anterior: 1. Defina o predicado arrecadacao(Filme, V) para determinar o valor arrecadado V com as locações do filme Filme. Considere que cada locação de filme custa R$ 5,00. arrecadacao(Filme, V) :- filme(X, Filme), locacoes(X, Y), V is 5 * Y. Exemplo de uso: ?- arrecadacao('Monty Python', V). V = 2500. 2. Expresse a seguinte consulta: Qual o nome do filme com identificador igual a 2? ?- filme(2, X). X = 'O Senhor dos Aneis'. 3. Expresse a seguinte consulta: Quais os identificadores e nomes dos filmes com mais de 100 locações? ?- filme(X, Y), locacoes(X, Z), Z > 100. X = 1, Y = 'Monty Python', Z = 500 ; X = 2, Y = 'O Senhor dos Aneis', Z = 1000 ; false. 3. Crie um programa Prolog contendo os seguintes fatos sobre países (nome, área em Km2 e população em milhões de habitantes): pais(brasil, 9, 130). pais(china, 12, 1800). pais(eua, 9, 230). pais(índia, 3, 450). 4. Considerando a base do exercício anterior: 1. Defina o predicado densidade(P) para determinar a densidade demográfica do país P. A densidade demográfica é dada pelo quociente entre a população e a área do país. densidade(P, Z) :- pais(P, X, Y), Z is Y/X. Exemplo de uso: ?- densidade(brasil, Z). Z = 14.4444. 2. Expresse a seguinte consulta: Qual a diferença entre a população da China e do Brasil? ?- pais(china, _, A), pais(brasil, _, B), X is A - B. A = 1800, B = 130, X = 1670. 3. Expresse a seguinte consulta: A densidade demográfica do Brasil é maior do que a dos Estados Unidos? ?- densidade(brasil, A), densidade(eua, B), A > B. false. 5. Crie um programa Prolog contendo a seguinte base de fatos Prolog: mulher(ana). % ana é uma mulher mulher(cecilia). mulher(joana). homem(joao). % joao é um homem homem(pedro). homem(leandro). filho(pedro, joao). % pedro é filho de joao filho(pedro, ana). % pedro é filho de ana filho(leandro, pedro). 6. Considerando a base do exercício anterior, defina os predicados: 1. neto(X,Y), para determinar se X é neto (sexo masculino) de Y neto(X,Y) :- filho(X, Z), filho(Z, Y), homem(X). 2. neta(X,Y), para determinar se X é neta (sexo feminino) de Y neta(X,Y) :- filho(X, Z), filho(Z, Y), mulher(X). Listas 1. Quais serão os resultados das seguintes consultas com unificação? ?- [A,B|L] = [1,2,3,4,5]. A = 1, B = 2, L = [3, 4, 5]. ?- [1,2,3] = [A,B|C]. A = 1, B = 2, C = [3]. ?- [1,2,3] = [A,B,C]. A = 1, B = 2, C = 3. ?- [1,2,3] = [A,B]. false. 2. O predicado nextto(X, Y, L) é pré-definido em Prolog e serve para determinar se um elemento Y segue um elemento X numa lista L. Em outras palavras, nextto determina se X está imediatamente à esquerda de Y na lista L. Considerando este predicado, o que é retornado pelas consultas abaixo? ?- nextto(b, c, [a,b,c,d,e]). ?- nextto(c, N, [a,b,c,d,e]). N = d. ?- nextto(X, e, [a,b,c,d,e]). X = d. ?- nextto(casa(azul), casa(verde), [casa(branca), casa(verde), casa(azul), casa(vermelha)]). false. 3. Defina um predicado ao_lado(X, Y, L) para determinar se X está imediatamente ao lado de Y na lista L. Neste caso, X pode estar imediatamente à esquerda ou à direita de Y. Use o predicado nextto do exercício anterior. ao_lado(X, Y, List) :- nextto(X, Y, List) ; nextto(Y, X, List). 4. Explique detalhadamente as definições do predicado deduzame abaixo: deduzame(A, A, [A]). deduzame(A, B, [A|R]) : A =< B, Num is A + 1, deduzame(Num, B, R). O predicado "deduzame(A, B, [C])" retorna "true" para o caso de A = X e B = Y onde X é o limite inferior e Y o limite superior de uma sequencia incremental de 1 (uma) unidade. Exemplo: ?- deduzame(-1, 2, [-1, 0, 1, 2]). true. E retorna "false" para quaisquer outras situações. 5. Qual será o resultado da consulta abaixo? (responda ANTES de testar no interpretador!) ?- deduzame(4, 7, L). L = [4, 5, 6, 7]. 6. Explique detalhadamente as definições do predicado pred abaixo: pred([], L, L). pred([H|T], L, [H|R]) :- pred(T, L, R). O predicado "pred(A, B, C)" verifica se a concatenação entre a lista A e a - lista ou numeral - B resulta na lista C. Exemplo: ?- pred([1,2,3], 4, L). L = [1, 2, 3|4]. ?- pred([4, 5, 6], [7], [4, 5, 6, 7]). true. 7. Qual será o resultado da consulta abaixo? (responda ANTES de testar no interpretador!) pred([4,5], [1], L). L = [4, 5, 1]. 8. Defina o predicado ultimo(E, L) para determinar se o elemento E é o último elemento da lista L. Você deverá usar recursão. Defina primeiro o caso base da recursão e depois o caso geral. Dica: lembre-se que você já fez algo semelhante em Haskell!. Exemplos de uso deste predicado: ?- ultimo(b, [a,b,c,d]). false. ?- ultimo(X, [a,b,c,d]). X = d . ultimo(E, [E]). ultimo(E, [H|R]) :- ultimo(E, R).
Clique aqui para ver a página com os enunciados! 1. Escreva um predicado em Prolog para determinar se há exatamente um elemento separando 2 dados elementos de uma lista. Assuma que a lista terá no mínimo 3 elementos. Exemplo de uso do predicado: ?- um_entre(b,c,[a,b,c,d]). false. ?- um_entre(b,d,[a,b,c,d]). true . ?- um_entre(a,d,[a,b,c,d]). false. um_entre(X, Y, [H|T]) :- X = H, T = [_|HS], HS = [A|_], Y = A. um_entre(X, Y, [_|T]) :- um_entre(X, Y, T).
Clique aqui para ver a página com os enunciados! Clique aqui para baixar o arquivo "fatoriais.pl". % Exerc1 b(2). b(3). c(4). c(5). regra1(X, Y) :- b(X), c(Y). regra2(X, Y) :- b(X), !, c(Y). % Exerc2 % Resposta: o resultado de ?- regra1(X, Y). serah % X = 2, % Y = 4 ; % X = 2, % Y = 5 ; % X = 3, % Y = 4 ; % X = 3, % Y = 5. % Exerc3 % Resposta: o resultado de ?- regra2(X,Y). serah % X = 2, % Y = 4 ; % X = 2, % Y = 5. % Exerc4 % Observar o "trace" de regra1 e regra2 % Exerc5 % Baixar fatoriais.pl e carrega-lo no swipl % Exerc6 % Executar ?- fatv1(3, N). e verificar se ha % outras possiveis respostas utilizando ";" % Exerc7 % Resposta: o erro se dah devido ao fato de nao haver % tratamento para o caso de entrada de numeros % negativos % Exerc8 % Utilizar modo "trace" para ?- fatv1(3,N). % Exerc9 % Resposta: fatv2 impede a continuidade da busca por % resultados e fatv3 faz uma "filtragem" % do valor para o qual se busca o fatorial % Exerc10 % Resposta: para ?- fatv2(3,N). ter-se-ah como resposta % N = 6. % Enquanto que, para fatv3(3,N). o resultado serah % N = 6 (permitindo ";", o qual retornarah) % false. % Exerc11 % Acompanhar as execucoes das consultas acima % com o modo trace ativado % Exerc12 % Resposta: fatv2 gera 21 "interacoes" antes de expor o resultado % final, enquanto que fatv3 gera 24, antes de expor % um primeiro resultado e 35, antes de expor o % resultado final.