Programação em Lógica, 2004/05
1º Teste
DI-FCT/UNL
13 de Maio de 2005
Programação em Lógica
1º Teste
Sem consulta - Duração: 2 horas
Notas Prévias: Deverá entregar exactamente 3 folhas, cada uma delas com a sua resolução de um
dos grupos do teste. Cada uma das folhas deve ter o seu nome, número de aluno e número do grupo
em causa (Grupo 1, Grupo 2 ou Grupo 3). Mesmo que não resolva um qualquer grupo, deve na mesma
entregar a folha, neste caso apenas com os dados acima.
Note que com estas regras não pode usar mais do que uma folha para responder a um grupo. Mas
uma folha para cada grupo deverá ser mais do que suficiente!
Grupo 1
Implemente em Prolog os predicados abaixo indicados. Em cada uma das alíneas, pode usar os
predicados das alíneas anteriores, mesmo que não os tenha feito. Neste grupo serão valorizadas as
respostas com recursividade terminal.
1 a)
divisivel(+N1,+N2) que sucede se e só se o número N1 for divisível por N2 (i.e se
N1 dividido por N2 der resto 0).
1 b)
divisivelNenhum(+N,+LN) que, dado um número N e uma lista de números em LN,
sucede se e só se o número N não for divisível por nenhum dos números em LN.
1 c)
primos(+N,-Primos), que devolve em Primos a lista de todos os números primos
menores ou iguais a um N dado. Por exemplo:
?- primos(40,P).
P = [37, 31, 29, 23, 19, 17, 13, 11, 7, 5, 3, 2];
no
Como sugestão, note que se já souber todos os números primos P até um dado X qualquer é
muito fácil determinar se Y=X+1 é primo: é primo se e só se não for divisível por nenhum
dos números em P.
Grupo 2
O que se pretende neste grupo é fazer um programa que ajude no plágio de trabalhos feitos em Prolog.
Claro que não deverá tentar fazer isto fora deste teste ☺
Mas vamos lá a isto. Para começar a primeira ideia é simples: arranja-se uma lista de “substituições” de
nomes; lê-se um ficheiro com o programa original, e cria-se um novo ficheiro igualzinho ao original
mas depois de feitas todas as substituições de nomes.
2 a)
Comece por implementar o predicado substituiTermo(+T1,-T2,+Subs) que aplica
no termo T1 todas as substituições na lista Subs, devolvendo o termo resultado em T2.
Uma lista de substituições é uma lista de pares V1-V2, denotando tal par que o valor V1
deve ser substituído por V2. Por exemplo:
?- substituiTermo( a(f(1),b(X,a)), T2, [a-aa,b-ola]).
T2 = aa(f(1),ola(X,aa));
no
2 b)
Faça agora o predicado plagio(+Original,+NovoFich,+Subs) que, dado em
Original o nome do ficheiro do programa original e em Subs a lista de substituições de
nomes, cria o ficheiro plagiado com o nome NovoFich.
Página 1 de 2
Programação em Lógica, 2004/05
1º Teste
Grupo 3
Todos vocês conhecem o jogo do galo. Por isso nem irei entrar em muitos detalhes sobre o que se trata
e como se joga. Apenas relembrando rapidamente: é um jogo de dois jogadores (chamemos x a um
deles e o ao outro), que se joga num tabuleiro de 3 por 3; de cada vez um jogador coloca uma marca
numa posição livre do tabuleiro; ganha aquele que primeiro conseguir 3 peças suas em linha (vertical,
horizontal ou diagonal); se se chegar a uma situação em que não há posições livres, e ninguém ganhou,
então o jogo termina empatado.
o
Para implementar um jogo do galo, a primeira coisa a fazer é escolher uma
estrutura de dados para representar o tabuleiro. Neste grupo, iremos assumir que
o
o tabuleiro é representado por uma lista com 3 listas (cada uma representando
uma linha do tabuleiro) de 3 elementos (cada um representando uma posição da
linha). Uma posição livre é representada por uma variável livre. Por exemplo, o
tabuleiro inicial, com todas as posições livres, pode ser representado por
[[P1,P2,P3],[P4,P5,P6],[P7,P8,P9]], e o tabuleiro da figura
[[o,x,P3],[o,x,x],[P7,o,P9]].
x
x
x
o
pela
lista
Vamos então fazer em Prolog alguns predicados que ajudam a jogar ao galo…
3 a)
posicaoLivre(+Tabuleiro,-Posicao) que sucede unificando a variável
Posicao com uma das variáveis livres (que corresponde a uma posição livre) no
Tabuleiro. Em backtracking deverão ser devolvidas, uma a uma, todas as possíveis
posições livres. Por exemplo, para o tabuleiro da figura:
?- T
P
P
P
no
=
=
=
=
[[o,x,P3],[o,x,x],[P7,o,P9]], posicaoLivre(T,P).
P3;
P7;
P9;
3 b)
jogada(?Tabuleiro,+Jogador) que sucede instanciando uma das posições livres do
Tabuleiro com a marca em Jogador. Em backtracking deverão ser devolvidas, uma a
uma, todas as possíveis instanciações.
3 c)
vitoria(+Tabuleiro,+Jogador) que sucede se e só se no Tabuleiro o
Jogador ganha (i.e. tem 3 peças em linha horizontal, vertical ou diagonal).
3 d)
boaJogada(?Tabuleiro,+Jogador), que instancia uma posição livre do tabuleiro
com uma jogada do Jogador, calculada de acordo com a seguinte estratégia: Se existe
alguma jogada que possibilita ao jogador ganhar imediatamente, então essa jogada deve ser
feita; caso contrário, se existir alguma posição livre onde caso o outro jogador aí jogasse
ganhava, então deve-se jogar para essa posição (evitando assim que o outro aí ganhe
imediatamente); caso contrário deve ser escolhida uma qualquer jogada. Por exemplo, para o
tabuleiro da figura, se for o o a jogar:
?- T = [[o,x,P3],[o,x,x],[P7,o,P9]], boaJogada(T,o).
T = [[o,x,P3],[o,x,x],[o,o,P9]]
P3=_
P7=o
no
porque assim o o ganha imediatamente. Se fosse o x a jogar:
P9=_ ;
?- T = [[o,x,P3],[o,x,x],[P7,o,P9]], boaJogada(T,x).
T = [[o,x,P3],[o,x,x],[x,o,P9]]
P3=_
P7=x
P9=_ ;
no
porque não lhe é possível ganhar imediatamente, e assim evita que o opositor ganhe logo a
seguir jogando para P7.
Note que, obviamente, esta não é a melhor estratégia para jogar ao galo. Mas a
implementação da melhor estratégia seria um pouco mais complicada e por isso neste teste
apenas vos é exigida esta simplificada.
Página 2 de 2
Download

1º Teste