====== Práctica Nro: 4 (Functores) ======
===== Enunciados =====
- Definir dominios para representar personas con nombre, apellido, edad, etc.\\
- Definir dominios para representar libros con nombre, autor, cantidad de páginas, etc.\\
- Definir dominios y predicados para representar la posesión de distintos tipos de objetos por personas.\\
- Definir dominios para representar en Prolog listas genéricas (o sea aquellas en las cuales cada elemento de la lista puede ser o bien átomo o bien una lista).\\
- Definir un predicado para imprimir una lista del tipo definido anteriormente.\\
- Definir un predicado para invertir una lista del tipo definido anteriormente, en todos sus niveles.\\
- Definir un predicado para calcular la profundidad de una lista del tipo definido anteriormente.\\
- Definir un predicado para planchar(colocar todos sus elementos atómicos en un solo nivel) una lista del tipo definido anteriormente.\\
----
===== Resueltos =====
==== Ej 1 ====
% Ej 1 de la guía 4.
% Definir dominios para representar personas con nombre, apellido, edad, etc.
domains
apellido, nombre = symbol
edad = integer
persona = persona (nombre, apellido, edad)
==== Ej 2 ====
% Ej 2 de la guía 4.
% Definir dominios para representar libros con nombre, autor, cantidad de páginas, etc.
domains
nombre_libro, autor = symbol
paginas = integer
libro = libro (nombre_libro, autor, paginas)
==== Ej 4 ====
% Ej 4 de la guía 4.
% Definir dominios para representar en Prolog listas genéricas (o sea aquellas en las cuales cada elemento de la lista puede ser o bien átomo o bien una lista).
domains
elemento = int (integer); list (lista)
lista = elemento*
==== Ej 5 ====
% Ej 5 de la guía 4.
% Definir un predicado para imprimir una lista del tipo definido anteriormente.
domains
elemento = int (integer); list (lista)
lista = elemento*
predicates
nondeterm imprimirLista (lista).
nondeterm imprimirEntero (integer).
clauses
imprimirEntero(Ca) :- write(Ca," ").
imprimirLista ([]).
imprimirLista([int(Ca)|Co]) :- imprimirEntero(Ca), imprimirLista(Co).
imprimirLista([list(Ca)|Co]) :- imprimirLista(Ca), imprimirLista(Co).
goal
imprimirLista([int(2),list([int(2),int(3)]),int(2),int(3),int(4)]).
==== Ej 5 (otra forma) ====
% Ej 5 de la guía 4.
% Definir un predicado para imprimir una lista del tipo definido anteriormente.
domains
elemento = int (integer); list (lista)
lista = elemento*
predicates
nondeterm imprimir (lista).
clauses
imprimir([]).
imprimir([Ca|Co]) :- write(Ca), imprimir(Co).
goal
imprimir([int(2),list([int(2),int(3)]),int(2),int(3),int(4)]).
==== Ej 7 ====
% Ej 7 de la guía 4.
% Definir un predicado para calcular la profundidad de una lista del tipo definido.
domains
entero = integer
elemento = int (entero); list (lista)
lista = elemento*
predicates
nondeterm profundidad(lista, entero).
clauses
profundidad([], Profundidad) :- Profundidad=0.
profundidad([int(_)|Co], Profundidad) :- ProfCa=1, profundidad(Co,ProfCo), ProfCa>ProfCo, Profundidad=ProfCa.
profundidad([int(_)|Co], Profundidad) :- ProfCa=1, profundidad(Co,ProfCo), ProfCa<=ProfCo, Profundidad=ProfCo.
profundidad([list(Ca)|Co], Profundidad) :- profundidad(Ca,ProfCa), profundidad(Co,ProfCo), ProfCo>=ProfCa+1, Profundidad=ProfCo.
profundidad([list(Ca)|Co], Profundidad) :- profundidad(Ca,ProfCa), profundidad(Co,ProfCo), ProfCo<=ProfCa, Profundidad=ProfCa+1.
goal
% Cero nivel de profundidad.
profundidad([], Profundidad0),
% Un nivel de profundidad.
profundidad([int(3)], Profundidad1),
% Dos niveles de profundidad.
profundidad([int(2),int(2),int(3),list([int(2),int(3)])], Profundidad2),
% Tres niveles de profundidad.
profundidad([list([int(2),int(3),list([int(2),int(3)])]),int(2),int(3),int(4)], Profundidad3),
% Cuatro niveles de profundidad.
profundidad([int(2),list([list([list([int(2),int(3)]),int(3)]),int(3)]),int(2),int(3),int(4)], Profundidad4),
write().
==== Ej 8 ====
% Ej 8 de la guía 4.
% Definir un predicado para planchar (colocar todos sus elementos atómicos en un solo nivel) una lista del tipo definido anteriormente.
domains
entero = integer
elemento = int (entero); list (lista)
lista = elemento*
listaEntero = entero*
predicates
nondeterm insertar (listaEntero, entero, listaEntero).
nondeterm union (listaEntero, listaEntero, listaEntero).
nondeterm planchar(lista, listaEntero).
clauses
union(Lista,[], Union) :- Union=Lista, !.
union([],Lista, Union) :- Union=Lista, !.
union([Ca|Co],L2, Union) :- union(Co,L2,Union2), Union=[Ca|Union2].
insertar (Lista, Entero, [Entero| Lista]).
planchar([],[]).
planchar([int(Entero)|Co], Salida) :- planchar(Co,ColaPlanchada), insertar (ColaPlanchada, Entero, Salida).
planchar([list(Ca)|Co], Salida) :- planchar(Ca,SalidaCa), planchar(Co,SalidaCo), union(SalidaCa,SalidaCo,Salida).
goal
planchar([], Lista0),
planchar([int(3)], Lista1),
planchar([int(2),int(2),int(3),list([int(2),int(3)])], Lista2),
planchar([list([int(2),int(3),list([int(2),int(3)])]),int(2),int(3),int(4)], Lista3),
planchar([int(2),list([list([list([int(2),int(3)]),int(3)]),int(3)]),int(2),int(3),int(4)], Lista4),
write().