Estruturas (Functors)

filósofo

Em Prolog, estruturas (também chamadas de functors) são a forma de criar objetos de dados complexos que agrupam múltiplos componentes sob um mesmo nome. Elas são equivalentes a registros em outras linguagens, permitindo modelar dados estruturados de forma natural e declarativa.

1. O que é uma Estrutura?

Uma estrutura em Prolog é um objeto composto que agrupa vários componentes (argumentos) sob um functor (um nome que identifica o tipo da estrutura). A sintaxe é:

Os componentes podem ser de qualquer tipo: átomos, números, variáveis ou até mesmo outras estruturas.

Exemplos de Estruturas

2. Estruturas como Dados vs. Fatos como Relacionamentos

É importante entender a diferença entre estruturas e fatos:

  • Estrutura: Um objeto de dados. Ex: ponto(3,5) é um dado que representa um ponto no plano.
  • Fato: Um relacionamento entre objetos. Ex: distancia(ponto(0,0), ponto(3,4), 5). é um fato que relaciona dois pontos e sua distância.

Estruturas podem aparecer como argumentos dentro de fatos e regras.

3. Programa 5.6: Acontecimentos Históricos

Vamos criar uma base de dados de acontecimentos históricos usando estruturas para representar datas:

Consultando Acontecimentos Históricos

1. Qual é o acontecimento de uma data específica?

2. Em que data ocorreu a Proclamação da República?

3. Quais acontecimentos ocorreram no mês de setembro?

4. Quais acontecimentos ocorreram no século XIX (anos 1800-1899)?

5. Extrair partes da data:

4. O Conceito de Functor

O functor é a “tag” ou “rótulo” que identifica o tipo da estrutura. Ele consiste no nome do functor e na sua aridade (número de argumentos).

Dois functors com o mesmo nome mas aridades diferentes são considerados diferentes. Por exemplo, data/3 (dia, mês, ano) e data/2 (mês, ano) são functors distintos.

5. Estruturas Aninhadas

Uma das grandes vantagens das estruturas é que elas podem ser aninhadas, permitindo modelar dados complexos de forma hierárquica.

Consultas com Estruturas Aninhadas

6. Exercícios Propostos

Pratique a criação e uso de estruturas com estes desafios:

  1. Livro: Crie uma estrutura livro/4 com título, autor, ano e ISBN. Adicione alguns fatos livro(...) e faça consultas para:
    • Encontrar todos os livros de um autor específico.
    • Encontrar livros publicados antes de 1950.
    • Extrair o ISBN de um livro pelo título.
  2. Funcionário: Crie uma estrutura funcionario/4 com nome, cargo, salário e departamento. Adicione fatos e consulte:
    • Funcionários com salário acima de 5000.
    • Funcionários de um determinado departamento.
    • Encontrar o salário de um funcionário pelo nome.
  3. Endereço aninhado: Crie uma estrutura pessoa/3 com nome, idade e endereco/4 (rua, número, cidade, estado). Adicione fatos e consulte:
    • Pessoas que moram em um determinado estado.
    • Pessoas que moram em uma determinada cidade.
    • Pessoas com idade acima de 18 anos.
  4. Pedido: Crie estruturas para representar um sistema de pedidos:
    • produto(Nome, Preco)
    • item(Produto, Quantidade)
    • pedido(Numero, Cliente, ListaDeItens, Total)
    Desafio: Calcule o total do pedido somando preco * quantidade.

7. Conclusão

As estruturas (functors) são uma ferramenta essencial em Prolog para:

  • Modelar dados complexos: Agrupe informações relacionadas em um único objeto.
  • Criar hierarquias: Aninhe estruturas para representar dados com múltiplos níveis.
  • Facilitar consultas: Use padrões de unificação para extrair componentes específicos.
  • Organizar o código: Dê nomes significativos aos seus dados usando functors.

Diferente de listas (que são sequências), estruturas têm componentes fixos e nomeados (pelo functor), o que as torna ideais para representar entidades do mundo real com atributos conhecidos.

Pratique com os exercícios e explore como estruturas podem tornar seus programas Prolog mais legíveis, organizados e expressivos!

Algoritmos Recursivos em Listas (Merge Sort)

filósofo

O Merge Sort é um algoritmo clássico de ordenação baseado no paradigma “dividir para conquistar”. Em Prolog, sua implementação é particularmente elegante devido à natureza recursiva das listas e ao poder da unificação. Vamos construir o algoritmo passo a passo.

1. O Paradigma “Dividir para Conquistar”

O Merge Sort segue três passos fundamentais:

  1. Distribuir (Dividir): A lista original é dividida em duas sublistas aproximadamente iguais.
  2. Ordenar recursivamente (Conquistar): Cada sublista é ordenada recursivamente usando o mesmo algoritmo.
  3. Intercalar (Combinar): As duas sublistas ordenadas são mescladas em uma única lista ordenada.

2. Passo 1: Distribuir — distribui/3 (Programa 5.4)

O predicado distribui/3 divide uma lista em duas, alternando os elementos entre elas.

Explicação Passo-a-Passo

  • distribui([], [], []): Se a lista está vazia, ambas as sublistas estão vazias.
  • distribui([X], [X], []): Se a lista tem um elemento, ele vai para a primeira lista.
  • distribui([X,Y|Z], [X|A], [Y|B]): O primeiro elemento X vai para A, o segundo Y vai para B, e a recursão distribui o restante Z.

Exemplo de Distribuição

3. Passo 2: Intercalar — intercala/3

O predicado intercala/3 mescla duas listas ordenadas em uma única lista ordenada.

Explicação Passo-a-Passo

  • intercala([], B, B): Se A está vazia, o resultado é B.
  • intercala(A, [], A): Se B está vazia, o resultado é A.
  • intercala([X|A], [Y|B], [X|C]): Se X ≤ Y, X é colocado na frente e a intercalação continua com A e [Y|B].
  • intercala([X|A], [Y|B], [Y|C]): Se X > Y, Y é colocado na frente e a intercalação continua com [X|A] e B.

Exemplo de Intercalação

4. Passo 3: Ordenar — ordena/2

O predicado ordena/2 combina distribuição, ordenação recursiva e intercalação.

5. Fluxo de Execução: ordena([3,5,0,4,1,2], S)

Vamos acompanhar a execução passo a passo:

Consulta Completa

6. Árvore de Recursão do Merge Sort

Visualize a árvore de recursão para ordena([3,5,0,4,1,2], S):

7. Análise de Complexidade

O Merge Sort tem complexidade:

  • Tempo: O(n log n) no pior caso, médio e melhor caso.
  • Espaço: O(n) para armazenar as sublistas durante a intercalação.

Em Prolog, a implementação é particularmente elegante porque:

  • A recursão natural do Prolog se alinha perfeitamente com a estrutura do algoritmo.
  • A unificação simplifica a distribuição e intercalação.
  • O código é declarativo e fácil de ler.

8. Exercícios Propostos

  1. Insertion Sort: Implemente o algoritmo Insertion Sort em Prolog.
    Dica: Use insere/3 para inserir um elemento em uma lista ordenada.
  2. Quick Sort: Implemente o Quick Sort em Prolog.
    Dica: Use um pivô (ex: o primeiro elemento) e divida a lista em menores e maiores.
  3. Bubble Sort: Implemente o Bubble Sort em Prolog.
    Dica: Use troca_uma_vez/2 e repita até a lista ficar ordenada.
  4. Selection Sort: Implemente o Selection Sort.
    Dica: Encontre o menor elemento, remova-o e ordene o resto.
  5. Comparação: Teste os diferentes algoritmos com listas de diferentes tamanhos e compare a eficiência em termos de tempo (use time/1).

9. Conclusão

O Merge Sort é um exemplo perfeito de como o Prolog pode expressar algoritmos complexos de forma elegante e declarativa. Com poucas linhas de código, implementamos um algoritmo eficiente de ordenação que é:

  • Correto: A recursão garante que todas as partes sejam ordenadas.
  • Eficiente: O(log n) para divisão e O(n) para intercalação.
  • Legível: Cada passo do algoritmo é claramente expresso em Prolog.

Dominar o Merge Sort em Prolog é um excelente exercício para entender como a recursão, a unificação e a divisão de listas se combinam para criar soluções poderosas.