Lista 2 de Prolog (versao 1)

Problema 1

A informação sobre um aluno é uma estrutura com RA, nota 1, nota 2 e nota 3.

aluno(RA,Nota1,Nota2,Nota3)
Cada nota representa a nota de uma prova e é um inteiro de 0 a 10, ou faltou se o aluno não fez a prova. A nota final do aluno é a média das 2 maiores notas, onde faltou corresponde a nota 0.

Escreva o predicado separa cujo primerio argumento é uma lista de informações com todos os alunos de uma classe; o segundo argumento é a lista dos RA dos alunos que passaram por ordem de RA, e o terceiro argumento é uma lista de estruturas exame(RA,precisa) por ordem crescente de precisa, onde precisa é quanto o aluno precisa tirar no exame, para ficar com 5.

Nota: é melhor usar o SWI neste exemplo. O SWI tem o predicado predsort que ordena uma lista usando um predicado extreno para fazer as comparações (como o sort do Lisp).

Problema 2

Dado um arquivo "dados.txt" com uma palavra por linha, milhares de linhas. Implemente o predicado conta sem argumentos, que imprime todas as palavras que aparecem no arquivo, com a sua frequencia, na ordem decrescente de frequencias (e se frequencias iguais, ordene as palavras usando o operador @> ou @< do Prolog (a ordem não é exatamente lexicografica - Obrigado ao Willians Casatti por ter descoberto isso!).

Ex: palavras aa aa bb aa cc bb cc estão no arquivo, uma por linha. A saida deverá ser:

aa 3
bb 2
cc 2

Nota: Esse problema é super chato em Prolog e portanto eu sugiro que voce o resolva por ultimo. Primeiro, leitura de strings em Prolog não é um predicado primitivo, segundo não há hash tables em prolog!!

Sobre a leitura, existe um predicado read_line escrito nos tempos pre-historicos do Prolog, que le uma linha do stream de entrada, e retorna no seu argumento uma lista de atomos e numeros que correspondem aos dados lidos na linha. Note que o read_line converte strings para atomos! Se tentar ler o EOF, o predicado retorna -1. Esse código esta aqui. Inclua esse predicado no seu codigo (mas existem predicados mais poderosos nas varias distribuições de prolog. Por exemplo, SWI tem o predicado readln mas é preciso saber usar os modulos para usa-lo.

Quanto ao hash, ha duas opções: implementa-lo usando assert e retract, que pode ser lento, ou implementar uma estrutura de dados que armazena pares, tipo uma lista, ou uma arvore binaria.

Problema 3

Um grafo direcionado aciclico é representado no arquivo "grafo.txt" como
n. [no-1 , no-1.1, no-1.2, no-1.3, ..., no-1.k].
[no-2, no-2.1, no-2.1, ..., no-2.m].
...
[no-n, ....].
onde n é o numero de vertices do grafo, e cada um dos no- é um inteiro. A linha
[no-2, no-2.1, no-2.1, ..., no-2.l].
diz que ha uma aresta de no-2 para no-2.1, outra aresta de no-2 para no-2.2, e assim por diante.

Por exemplo

3.
[1, 2].
[3, 1, 2].
representa o grafo de 3 vertices com arestas (1 2) (3 1) e (3 2).

Implemente o predicado grafo, que le o arquivo e retorna como seu unico argumento uma lista com uma ordenação topologica do grafo lido. Voce pode assumir (não precisa testar) que o grafo será aciclico e portanto terá pelo menos uma ordenação topologica.

No exemplo acima, a chamada a grafo(X) retorna

?- grafo(X). X = [3,1,2]

Nota: da mesma forma que em Lisp, a entrada foi alterada para tornar a vida de ler os dados mais facil. Aqui a linha interia pode ser lida com o read do Prolog.