Dados compostos. Paradigma de Programação Lógico. Marco A L Barbosa

Documentos relacionados
Acumuladores. Paradigma de Programação Funcional. Marco A L Barbosa

Fundamentos. Paradigma de Programação Lógico. Marco A L Barbosa

CAPÍTULO 3 - TIPOS DE DADOS E IDENTIFICADORES

Pedro Vasconcelos DCC/FCUP. Programação Funcional 14 a Aula Tipos abstratos de dados

Pedro Vasconcelos DCC/FCUP. Programação Funcional 15 a Aula Árvores de pesquisa

Memória Flash. PdP. Autor: Tiago Lone Nível: Básico Criação: 11/12/2005 Última versão: 18/12/2006. Pesquisa e Desenvolvimento de Produtos

Um jogo de preencher casas

x0 = 1 x n = 3x n 1 x k x k 1 Quantas são as sequências com n letras, cada uma igual a a, b ou c, de modo que não há duas letras a seguidas?

Orientação a Objetos

EAD Árvore árvore binária

Usando o Excel ESTATÍSTICA. Funções

Programação Funcional. Capítulo 1. Introdução. José Romildo Malaquias. Departamento de Computação Universidade Federal de Ouro Preto 2015.

*%# ## (+& ', # )&* ## - () ' #.# %&/.# ' '# () 0 *&# */ #,$1$ # * * ()% " ## # * 23 (), ) 45&26, ' 1#45 6'&#1#&# &7 ; '# *23) 8=9 =()/ / =:7

Programação WEB I Estruturas de controle e repetição

PROGRAMAÇÃO II 4. ÁRVORE

Projeto de Máquinas de Estado

5 Equacionando os problemas

Estruturas de Dados Pilhas, Filas e Deques

RESOLUÇÃO DAS QUESTÕES DE RACIOCÍNIO LÓGICO-MATEMÁTICO

Disciplina: Unidade III: Prof.: Período:

NOTAÇÃO MUSICAL TRADICIONAL: Como se escrever música?

Nesta aula serão apresentados alguns comandos de condição, repetição e gráficos.

Dadas a base e a altura de um triangulo, determinar sua área.

Programação em Lógica com Restrições Exame sem consulta - Duração: 3 horas

Microsoft Access: Criar consultas para um novo banco de dados. Vitor Valerio de Souza Campos

Sistemas de numeração

PROGRAMAÇÃO ESTRUTURADA. CC 2º Período

Pesquisa em Memória Primária. Prof. Jonas Potros

EXEMPLO DE COMO FAZER UMA MALA DIRETA

Microsoft Excel 2007

Linguagem Lógica Prolog

Função E. Excel 2007 Avançado. Sintaxe: Onde: Objetivo : 22 anos ou mais e casadas maiores de 21 anos.

Programação Orientada a Objetos. Prof. Diemesleno Souza Carvalho diemesleno@iftm.edu.br

Por que o quadrado de terminados em 5 e ta o fa cil? Ex.: 15²=225, 75²=5625,...

INF PROGRAMAÇÃO II LISTA DE EXERCÍCIOS 15

Cotagens especiais. Você já aprendeu a interpretar cotas básicas

O modelo do computador

e à Linguagem de Programação Python

GAAL /1 - Simulado - 1 Vetores e Produto Escalar

Algoritmos e Estruturas de Dados 2

No cálculo de porcentagem com operações financeiras devemos tomar muito cuidado para verificar sobre quem foi calculada essa porcentagem.

Aulas de PHP Criptografia com Cifra de César. Paulo Marcos Trentin

Exercícios resolvidos sobre Definição de Probabilidade

1. Visual Paradigm for UML

Busca. Pesquisa sequencial

O Excel é um programa de computador desenvolvido para gerenciar dados na forma de planilhas.

Introdução. Introdução. Objetivos da Aula. Bases Computacionais da Ciência(BC-0005)

Objetos Estruturados Listas Recursão Exercícios. Inteligência Artificial

Conceitos de relação de confiança

Roteiro de Aula Prática

Ambos têm os algarismos 7854 seguidos, a potência de dez apenas moverá a vírgula, que não afeta a quantidade de algarismos significativos.

FÓRMULAS DO EXCEL QUE SALVARAM MEU EMPREGO

ALGORITMOS E ESTRUTURAS DE DADOS CES-11 CES-11 CES-11

ESTRUTURAS DE DADOS II

a 1 x a n x n = b,

Associação Educacional Dom Bosco Curso de Engenharia 1º ano

Árvores Binárias. Observação: Material elaborado a partir do material do Professor Marcos Costa.

Universidade do Minho. Licenciatura em Engenharia Informática. Desenvolvimento de Sistemas de Software. Gere Com Saber

Resolução de sistemas lineares

4.10 Solução das Equações de Estado através da Transformada de Laplace Considere a equação de estado (4.92)

Tutorial Baseado em video do Sr. Rafael Streda.

ARRAYS. Um array é um OBJETO que referencia (aponta) mais de um objeto ou armazena mais de um dado primitivo.

BDII SQL Junção Revisão 8

Exercícios Teóricos Resolvidos

REDES DE COMPUTADORES - I UNI-ANHANGUERA. CURSO DE ANÁLISE E DESENVOLVIMENTO DE SISTEMAS PROF. MARCIO BALIAN

CRIANDO BANCOS DE DADOS NO SQL SERVER 2008 R2 COM O SQL SERVER MANAGEMENT STUDIO

Aula 4 Estatística Conceitos básicos

Estrutura de Dados Básica

MICROSOFT EXCEL AVANÇADO

Figure 2 - Nós folhas de uma árvore binária representando caracteres ASCII

Algoritmos em Javascript

Tutorial 5 Questionários

UM CONCEITO FUNDAMENTAL: PATRIMÔNIO LÍQUIDO FINANCEIRO. Prof. Alvaro Guimarães de Oliveira Rio, 07/09/2014.

Estruturas de Dados. Prof. Gustavo Willam Pereira Créditos: Profa. Juliana Pinheiro Campos

OPERADORES E ESTRUTURAS DE CONTROLE

1. FUNÇÕES NO EXCEL 2007

Programação Funcional. Capítulo 13. Mônadas. José Romildo Malaquias. Departamento de Computação Universidade Federal de Ouro Preto 2013.

PARA CASA * Como voce faria para armazenar o resultado em uma variavel chamada NOME?

Como meter legendas Definitivas num filme?

COMO OTIMIZAR A SUA PLANILHA ATRAVÉS DA GRAVAÇÃO DE UMA MACRO EM EXCEL

Parte I. Demoiselle Mail

O Problema do Troco Principio da Casa dos Pombos. > Princípios de Contagem e Enumeração Computacional 0/48

Departamento de Matemática - UEL Ulysses Sodré. Arquivo: minimaxi.tex - Londrina-PR, 29 de Junho de 2010.

Transformada z. ADL 25 Cap 13. A Transformada z Inversa

ÁRVORES BINÁRIAS DE PESQUISA

Segurança de Acesso a Banco de Dados no MS SQL Server

- UNIVERSIDADE DO VALE DO RIO DOS SINOS CIÊNCIAS EXATAS E TECNOLÓGICAS Curso: Informática / Ciência da Computação

ETEC DR. EMÍLIO HENRNANDEZ AGUILAR PROGRAMAÇÃO DE COMPUTADORES II PROFESSOR RAFAEL BARRETO DELPHI FORMULÁRIO COM ABAS E BUSCAS DE REGISTROS

1. Criar uma nova apresentação

Algoritmos e Programação (Prática) Profa. Andreza Leite andreza.leite@univasf.edu.br

Introdução aos cálculos de datas

Javascript 101. Parte 2

Lema do Bombeamento Linguagens Livres de Contexto

Diagramasde Interação. Prof. Anderson Cavalcanti UFRN-CT-DCA

Cotagem de dimensões básicas

Solução do Problema de Descontagem Indevida no Sistema de Bilhetagem do METRÔ

Múltiplos Estágios processo com três estágios Inquérito de Satisfação Fase II

&XUVRGH,QWURGXomRDR (GLWRUGH3ODQLOKDV([FHO

ESTRUTURAS DE DADOS II MSc. Daniele Carvalho Oliveira

Inventario de produtos

Transcrição:

Dados compostos Paradigma de Programação Lógico Marco A L Barbosa cba Este trabalho está licenciado com uma Licença Creative Commons - Atribuição-CompartilhaIgual 4.0 Internacional. http://github.com/malbarbo/na-func

Conteúdo Listas Receita de projeto Escrevendo predicados (semi) determinísticos Otimizações

Listas

Listas Podemos representar uma lista em Prolog de forma semelhante a listas em Racket Uma lista é Exemplos vazia; ou cons(a, B), onde A é um termo qualquer e B é uma lista?- L0 = vazio, L1 = cons(3, vazio), L2 = cons(3, cons(4, vazio)). L0 = vazia, L1 = cons(3, vazia), L2 = cons(3, cons(4, vazia)). A lista L0 é vazia, a lista L1 contém apenas o elemento 3 e a lista L2 contém os elemento 3 e 4 4 / 61

Listas Vamos definir um predicado para verificar se um termo é uma lista % lista(+x) is semidet % % Verdadeiro se X é uma lista. lista(vazia). lista(cons(_, B)) :- lista(b). 5 / 61

Listas Consultas?- lista(vazia). true.?- lista(cons(3, vazia)). true.?- lista(cons(3, cons(4, vazia))). true.?- lista(cons). false.?- lista(cons(3, 4)). false. Observe que não existe nada diferente do vimos anteriormente. O truque é que estamos usando estruturas recursivas 6 / 61

Listas O Prolog já entende uma definição de lista semelhante a nossa [] ao invés de vazia. ao invés de cons 7 / 61

Listas Exemplos?- L0 = [], L1 =. (3, []), L2 =. (3,. (4, [])). L0 = [], L1 = [3], L2 = [3, 4].?- write( L0 = ), write_canonical([]). L0 = []?- write( L1 = ), write_canonical(. (3, [])). L1 =. (3,[])?- write( L2 = ), write_canonical(. (3,. (4, []))). L2 =. (3,. (4,[])) Observe que na hora de escrever a lista o Prolog utiliza uma notação mais amigável, mas podemos ver que a representação interna utiliza termos. 8 / 61

Listas Podemos utilizar esta notação amigável para definir listas?- L0 = [], L1 = [3], L2 = [3, 4]. L0 = [], L1 = [3], L2 = [3, 4]. 9 / 61

Listas Podemos utilizar uma lista já existente para definir outra lista?- X = [1, 2, 3], Y =. (5, X). X = [1, 2, 3], Y = [5, 1, 2, 3]. ou usando uma sintaxe mais amigável?- X = [1, 2, 3], Y = [ 5 X ], Z = [3, 4 X]. X = [1, 2, 3], Y = [5, 1, 2, 3], Z = [3, 4, 1, 2, 3]. A notação [ A B ] é equivalente a. (A, B)?- X =. (3,. (4, [])), Y = [3 [4 []]], Z = [3, 4]. X = Y, Y = Z, Z = [3, 4]. 10 / 61

Listas Como obter os componentes de uma lista? Da mesma forma que obtemos os componentes de outras estruturas, usando unificação Lembre-se, uma lista é um termo e pode ser usado da mesma forma que qualquer outro termo 11 / 61

Listas / Exemplos?-. (A, B) =. (7,. (3,. (4, []))). A = 7, B = [3, 4].?- [A B] =. (7,. (3,. (4, []))). A = 7, B = [3, 4].?- [A B] = [7 [3 [4 []]]]. A = 7, B = [3, 4].?- [A B] = [7, 3, 4]. A = 7, B = [3, 4]. 12 / 61

Listas / Exemplos?- [A, B C] = [7, 3, 4]. A = 7, B = 3, C = [4].?- [A, B, C] = [7, 3, 4]. A = 7, B = 3, C = 4. 13 / 61

Receita de projeto

Receita de projeto Podemos seguir a mesma receita de projeto que usávamos para escrever funções em Racket De forma semelhante ao Racket, para cada tipo de dado, usamos um template O template é baseado na definição do dado Como a definição de lista tem dois casos, o template para lista também têm dois casos pred_lista([],...) :-???. pred_lista([x XS],...) :- pred_lista(xs,...),??? X. Observe que quando a lista não é vazia, pode ser necessário criar outros casos 15 / 61

Exemplo 1 Defina um predicado tamanho(l, T) que é verdadeiro se a quantidade de elementos na lista L é T. (Veja o predicado pré-definido length/2). 16 / 61

Exemplo 1 :- use_module(library(plunit)). % tamanho(?xs,?t) is semidet % % Verdadeiro se o tamanho de XS é T. :- begin_tests(tamanho). test(t0) :- tamanho([], 0). test(t1) :- tamanho([4], 1). test(t2, T == 2) :- tamanho([7, 2], T). :- end_tests(tamanho). tamanho([_ XS], T) :- tamanho(xs, T0), T is T0 + 1. tamanho([], 0). 17 / 61

Exemplo 1 % Leitura em portugu^es do predicado % O tamanho da lista [ _ XS ] é T se % T0 é o tamanho da lista XS e % T é T0 + 1 tamanho([_ XS], T) :- tamanho(xs, T0), T is T0 + 1. % O tamanho da lista [] é 0. tamanho([], 0). Resultado dos testes?- run_tests(tamanho). % PL-Unit: tamanho... done % All 3 tests passed true. 18 / 61

Exemplo 2 Defina um predicado kesimo(xs, K, N) que é verdadeiro se N é o K-ésimo elemento da lista XS. (Veja o predicado pré-definido nth0/3) 19 / 61

Exemplo 2 % kesimo(+xs, +K,?N) is semidet % % Verdadeiro se N é o K-ésimo elemento da lista XS. :- begin_tests(kesimo). test(t0) :- kesimo([5, 3, 10], 0, 5). test(t1) :- kesimo([5, 3, 10], 1, 3). test(t2, N == 10) :- kesimo([5, 3, 10], 2, N). test(t4, [fail]) :- kesimo([5, 3, 10], 4, _). :- end_tests(kesimo). kesimo([x _], 0, X). kesimo([_ XS], K, X) :- K > 0, K0 is K - 1, kesimo(xs, K0, X). 20 / 61

Exemplo 2 Observe que usamos o argumento [fail] para testar que o predicado falha Observe que neste caso o template utilizado foi para números naturais. Um número natural ou é 0 ou > 0 e pode ser diminuído 21 / 61

Exemplo 2 % Leitura em portugu^es do predicado % X é 0-ésimo elemento da lista [X _]. kesimo([x _], 0, X). % X é o K-ésimo elemento da lista [_ XS] se % K > 0 e % K0 é K - 1 e % X é o K0-ésimo elemento da lista XS kesimo([_ XS], K, X) :- K > 0, K0 is K - 1, kesimo(xs, K0, X). 22 / 61

Exemplo 2 Resultado dos testes (What!?)?- run_tests(kesimo). % PL-Unit: kesimo Warning: /home/malbarbo/desktop/x.pl:39: PL-Unit: Test t0: Test succeeded with choicepoint Warning: /home/malbarbo/desktop/x.pl:40: PL-Unit: Test t1: Test succeeded with choicepoint Warning: /home/malbarbo/desktop/x.pl:41: PL-Unit: Test t2: Test succeeded with choicepoint. done % All 4 tests passed true. 23 / 61

Escrevendo predicados (semi) determinísticos

Escrevendo predicados (semi) determinísticos Os testes (por padrão) esperaram que o predicado seja determinístico ou semi determinístico, mas depois de ser satisfeito uma vez, o predicado kesimo está oferecendo a possibilidade de ressatisfação, ou seja, ele é não determinístico?- kesimo([5, 3, 10], 1, 3). true ; false. 25 / 61

Escrevendo predicados (semi) determinísticos Porque o predicado tamanho não teve este problema? Teoricamente o predicado tamanho também deveria apresentar este problema, isto porque após a consulta ser satisfeita unificando com a primeira cláusula do predicado tamanho, o Prolog deveria oferecer a possibilidade de continuar a busca e tentar a unificação com a segunda cláusula, o que criaria o ponto de escolha Isto não acontece porque o SWI-prolog faz uma otimização. Ele só faz a busca entre as cláusulas do predicado que tenham o primeiro argumento compatível com a consulta Se o primeiro argumento da consulta é uma constante, ele tenta as cláusula que o primeiro argumento seja a mesma constante da consulta ou uma variável Se o primeiro argumento da consulta é uma variável, ele tenta todas as cláusulas Se o primeiro argumento da consulta é uma estrutura, ele tenta as cláusula que o primeiro argumento seja uma estrutura com o mesmo functor da estrutura da consulta ou uma variável 26 / 61

Escrevendo predicados (semi) determinísticos Considerando a definição de tamanho tamanho([_ XS], T) :- tamanho(xs, T0), T is T0 + 1. tamanho([], 0). Observamos que o primeiro argumento da primeira cláusula é a estrutura., e o primeiro argumento da segunda cláusula é a constante [] Seguindo a otimização do SWI-Prolog, em uma consulta tamanho com o primeiro argumento [], o interpretador tentará a unificação apenas com a segunda cláusula. Em uma consulta com uma lista não vazia como primeiro argumento, o interpretador tentará a unificação apenas com a primeira cláusula Vamos ver o que acontece com a definição de kesimo 27 / 61

Escrevendo predicados (semi) determinísticos Considerando a definição kesimo([x _], 0, X). kesimo([_ XS], K, X) :- K > 0, K0 is K - 1, kesimo(xs, K0, X). Neste caso o primeiro argumento das duas cláusulas é a estrutura.. Isto implica que em qualquer consulta que o primeiro argumento seja uma lista, o interpretador tentará as duas cláusulas, o que pode gerar um ponto de escolha Conceitualmente o predicado kesimo é semi determinísticos, mas a nossa implementação é não determinística, como resolver este problema? 28 / 61

Escrevendo predicados (semi) determinísticos O Prolog tem o operador de corte (!) que pode ser usado, entre outras coisas, para confirmar uma escolha e evitar que o interpretador faça outras tentativas % usamos o operador de corte para confirmar a escolha, % desta forma, se uma consulta for satisfeita unificando com % a primeira cláusula, a segunda n~ao será considerada kesimo([x _], 0, X) :-!. kesimo([_ XS], K, X) :- K > 0, K0 is K - 1, kesimo(xs, K0, X). Veremos em outro momento todos os usos e o funcionamento detalhado do operador de corte Observe que o operador de corte não faz parte do paradigma lógico Outra alternativa seria colocar o K como primeiro argumento. Porque isto também resolveria o problema? 29 / 61

Escrevendo predicados (semi) determinísticos Vamos voltar ao predicado tamanho tamanho([_ XS], T) :- tamanho(xs, T0), T is T0 + 1. tamanho([], 0). O que acontece na consulta??- tamanho(xs, 3). 30 / 61

Escrevendo predicados (semi) determinísticos Vamos voltar ao predicado tamanho tamanho([_ XS], T) :- tamanho(xs, T0), T is T0 + 1. tamanho([], 0). O que acontece na consulta??- tamanho(xs, 3). Entra em laço. A consulta unifica com a primeira cláusula, a primeira meta unifica novamente com a primeira cláusula e assim por diante Neste caso o operador de corte sozinho não resolve o problema é necessário fazer duas definições Uma para o caso que em XS está instanciado e outro para o caso em que XS não está instanciado Usamos os predicados pré-definidos nonvar e var, respectivamente 30 / 61

Escrevendo predicados (semi) determinísticos Nova versão tamanho([], 0) :-!. tamanho([_ XS], T) :- nonvar(xs), tamanho(xs, T0), T is T0 + 1,!. tamanho([_ XS], T) :- var(xs), T0 is T - 1, tamanho(xs, T0). 31 / 61

Escrevendo predicados (semi) determinísticos O que acontece nas consultas??- length(xs, T)....?- tamanho(xs, T).... Como alterar a definição de tamanho para funcionar da mesma forma que length? 32 / 61

Exemplo 3 Defina um predicado comprimida(xs, YS) que é verdadeiro se lista YS é XS comprimida, isto é, sem elementos repetidos consecutivos. 33 / 61

Exemplo 3 % comprimida(+xs,?ys) is semidet % % Verdadeiro se XS comprimida é YS, isto é, sem elementos repetidos % consecutivos. :- begin_tests(comprimida). test(t0) :- comprimida([], []). test(t1) :- comprimida([x], [x]). test(t2) :- comprimida([3, 3, 3, 4, 4, 3, 5, 5, 5], [3, 4, 3, 5]). :- end_tests(comprimida). 34 / 61

Exemplo 3 comprimida([], []). % elemento repetido comprimida([x XS], YS) :- comprimida(xs, YS), [X _] = YS. % elemento distinto comprimida([x XS], [X YS]) :- comprimida(xs, YS), [X _] \= YS. 35 / 61

Exemplo 3 Resultado dos testes?- run_tests(comprimida). % PL-Unit: comprimida. Warning: /home/malbarbo/desktop/x.pl:71: PL-Unit: Test t1: Test succeeded with choicepoint Warning: /home/malbarbo/desktop/x.pl:72: PL-Unit: Test t2: Test succeeded with choicepoint done % All 3 tests passed true. 36 / 61

Exemplo 3 Solução usando corte para tornar o predicado semi determinístico % comprimida(+xs,?ys) is semidet % % Verdadeiro se XS comprimida é YS, isto é, sem elementos repetidos % consecutivos. comprimida([], []). % elemento repetido comprimida([x XS], YS) :- comprimida(xs, YS), [X _] = YS,!. % elemento distinto comprimida([x XS], [X YS]) :- comprimida(xs, YS), [X _] \= YS. 37 / 61

Exemplo 3 Usamos o template para listas. Caso a lista não seja vazia, existem duas alternativas, o elemento é repetido ou não é repetido. Como estas duas alternativas são excludentes, usamos o operador de corte 38 / 61

Exemplo 3 Solução alternativa % comprimida2(+xs,?ys) is semidet % % Verdadeiro se XS comprimida é YS, isto é, sem elementos repetidos % consecutivos. :- begin_tests(comprimida2). test(t0) :- comprimida2([], []). test(t1) :- comprimida2([x], [x]). test(t2) :- comprimida2([3, 3, 4, 4, 4, 3, 5, 5, 5], [3, 4, 3, 5]). :- end_tests(comprimida2). 39 / 61

Exemplo 3 Continuação da solução alternativa comprimida2([], []). comprimida2([x], [X]) :-!. comprimida2([x, X XS], YS) :- comprimida2([x XS], YS),!. comprimida2([x, Y XS], [X YS]) :- X \= Y, comprimida2([y XS], YS). 40 / 61

Exemplo 4 Defina um predicado membro(x, XS) que é verdadeiro se X é membro de XS. Defina uma versão que seja não determinística e outra que seja semi determinística. (Veja os predicados pré-definido member/2 e memberchk/2) 41 / 61

Exemplo 4 % membro(?x,?xs) is nondet % % Verdadeiro se X é um elemento de XS. :- begin_tests(membro). test(t0, [nondet]) :- membro(1, [1, 1, 3, 7]). test(t1, [nondet]) :- membro(3, [1, 3, 7]). test(t2, [nondet]) :- membro(7, [1, 3, 7]). test(t3, all(x == [1, 3, 7])) :- membro(x, [1, 3, 7]). :- end_tests(membro). membro(x, [X _]). membro(x, [_ XS]) :- membro(x, XS). 42 / 61

Exemplo 4?- membro(x, [1, 3, 7]). X = 1 ; X = 3 ; X = 7 ; false.?- membro(x, L). L = [X _G279] ;... 43 / 61

Exemplo 4 Observe que o predicado membro é não determinístico Para testar predicados não determinísticos usados o argumento [nondet] Para testar todas as respostas de um predicado não determinísticos usamos o termo all Como definir uma versão semi determinística deste predicado? 44 / 61

Exemplo 4 Usando o operador de corte % membrochk(+x,?xs) is semidet % % Verdadeiro se X é um elemento de XS. :- begin_tests(membrochk). test(t0) :- membrochk(1, [1, 3, 7]). test(t1) :- membrochk(7, [1, 3, 7]). test(t2, X == 1) :- membrochk(x, [1, 3, 7]). test(t3, [fail]) :- membrochk(5, [1, 3, 7]). :- end_tests(membrochk). membrochk(x, [X _]) :-!. membrochk(x, [_ XS]) :- membrochk(x, XS). Usando o predicado pré-definido once membrochk(x, XS) :- once(membro(x, XS)). 45 / 61

Exemplo 5 Defina um predicado concatena(xs, YS, ZS) que é verdadeiro se ZS é XS concatenado com YS. (Veja o predicado pré-definido append/3) 46 / 61

Exemplo 5 % concatena(?xs,?ys,?zs) is nondet % % Verdadeiro se ZS é YS concatenado com ZS. :- begin_tests(concatena). test(t0) :- concatena([1, 2], [3, 4, 5], [1, 2, 3, 4, 5]). test(t1, XS == [1, 2, 4]) :- concatena(xs, [3], [1, 2, 4, 3]). test(t2, YS == [4, 3]) :- concatena([1, 2], YS, [1, 2, 4, 3]). test(t3, all(p(xs, YS) == [ p([], [1, 2, 3]), p([1], [2, 3]), p([1, 2], [3]), p([1, 2, 3], [])])) :- concatena(xs, YS, [1, 2, 3]). :- end_tests(concatena). 47 / 61

Exemplo 5 concatena([], YS, YS). concatena([x XS], YS, [X XSYS]) :- concatena(xs, YS, XSYS). 48 / 61

Exemplo 5 Resultado dos testes?- run_tests(concatena). % PL-Unit: concatena. Warning: /home/malbarbo/desktop/ex_dados.pl:46: PL-Unit: Test t1: Test succeeded with choicepoint.. done % All 4 tests passed true. Porque? Solução Na consulta concatena(xs, [3], [1, 2, 4, 3]) são testadas as duas cláusula, gerando a escolha Adicionar o operador de corte na primeira cláusula faz com que o teste t3 falhe... Adicionar nondet ao teste t1 49 / 61

Exemplo 5 % concatena(?xs,?ys,?zs) is nondet % % Verdadeiro se ZS é YS concatenado com ZS. :- begin_tests(concatena). test(t0) :- concatena([1, 2], [3, 4, 5], [1, 2, 3, 4, 5]). test(t1, [nondet, XS == [1, 2, 4]]) :- concatena(xs, [3], [1, 2, 4, 3]). test(t2, YS == [4, 3]) :- concatena([1, 2], YS, [1, 2, 4, 3]). test(t3, all(p(xs, YS) == [ p([], [1, 2, 3]), p([1], [2, 3]), p([1, 2], [3]), p([1, 2, 3], [])])) :- concatena(xs, YS, [1, 2, 3]). :- end_tests(concatena). 50 / 61

Exemplo 5 concatena([], YS, YS). concatena([x XS], YS, [X XSYS]) :- concatena(xs, YS, XSYS). 51 / 61

Listas aninhadas Uma lista aninhada é Template []; ou [X XS], onde X não é uma lista aninhada e XS é uma lista aninhada; ou [X XS], onde X e XS são listas aninhadas pred_lista_aninhada([],...) :-???. pred_lista_aninhada([x XS],...) :- \+ is_list(x), pred_lista_aninhada(xs,...),??? X. pred_lista_aninhada([x XS],...) :- pred_lista_aninhada(x,...), pred_lista_aninhada(xs,...),???. 52 / 61

Exemplo 6 Defina um predicado super soma(xs, S) que é verdadeiro se S é soma de todos os elementos da lista aninhada XS. 53 / 61

Exemplo 6 % super_soma(xs, S) is semidet % % Verdadeiro se S é a soma de todos elementos da lista aninhada XS. :- begin_tests(super_soma). test(t0) :- super_soma([[], [], [[], []]], 0). test(t1) :- super_soma([[1], [2, 3], [4, [5, 6], 7]], 28). test(t2, S == 36) :- super_soma([[1, 2], 3, [4, [5, 6, [7]], 8]], S). :- end_tests(super_soma). 54 / 61

Exemplo 6 super_soma([], 0). super_soma([x XS], S) :- \+ is_list(x),!, super_soma(xs, S1), S is X + S1. super_soma([x XS], S) :- super_soma(x, S1), super_soma(xs, S2), S is S1 + S2. 55 / 61

Árvore binária Uma árvore binária é: Template nil; ou t(x, L, R) onde X é o elemento raiz e L é a sub árvore a esquerda e R é a sub árvore a direita pred_arvore_binaria(nil,...) :-???. pred_arvore_binaria(t(x, L, R),...) :- pred_arvore_binaria(l,...), pred_arvore_binaria(r,...),??? X. 56 / 61

Exemplo 7 Defina um predicado altura(t, H) que é verdadeiro se H é altura da árvore binária T. A altura de uma árvore binária é a distância entre a raiz e o seu descendente mais afastado. Uma árvore com um único nó tem altura 0. 57 / 61

Otimizações

Otimizações Assim como o Racket, o Prolog faz otimizações das chamadas recursivas em cauda As vezes é necessário utilizar acumuladores para transformar uma recursão em recursão em cauda Uma outra técnica de otimização comum em Prolog é a utilização de diferenças de listas 59 / 61

Otimizações / Acumuladores Exemplo em sala 60 / 61

Otimizações / Diferenças de listas Exemplo em sala 61 / 61