Práctica de Prolog: Avanzados (Paradigmas)

De Cuba-Wiki
Saltar a: navegación, buscar
Back.png Volver a la página de la materia

% Ejercicio 16
% Definir el predicado combinador(+L,+D,+H,-XS), que debe dar verdadero cuando XS es una lista de
% naturales de longitud L, y cada uno de sus elementos XSi cumple que D � XSi � H. No se deben devolver
% soluciones repetidas.
% Por ejemplo: combinador(2,3,5,X).
% X = [3,3] ;
% X = [3,4] ;
% X = [3,5] ;
% X = [4,3] ;
% X = [4,4] ;
% X = [4,5] ;
% X = [5,3] ;
% X = [5,4] ;
% X = [5,5] ;

%in_range(+Min, +Max, -Min).
in_range(Min, Max, Min) :- Min =< Max.
in_range(Min, Max, N) :- Min =< Max, NextMin is Min + 1, in_range(NextMin, Max, N).

%combinador(+L, +D, +H, -XS).
combinador(0, _, _, []).
combinador(L, Min, Max, [H | T]) :- L > 0, in_range(Min, Max, H), L1 is L - 1, combinador(L1, Min, Max, T).

% Ejercicio 17
% Un cuadrado semi-latino es una matriz cuadrada de naturales (incluido el cero) donde todas las filas
% de la matriz suman lo mismo. Por ejemplo:
% 1 3 0
% 2 2 0 todas las filas suman 4
% 1 1 2
% Representamos la matriz como una lista de filas, donde cada fila es una lista de naturales. El ejemplo
% anterior se representar´ia de la siguiente manera: [[1,3,0],[2,2,0],[1,1,2]].
% Se pide definir el predicado cuadradoSemiLatino(N,XS). El par´ametro N debe estar instanciado, y
% XS no puede estar instanciado. El predicado debe ir devolviendo matrices (utilizando la representaci
% ´on antes mencionada), que sean cuadrados semi-latinos de dimensi´on N*N. Dichas matrices deben
% devolverse de manera ordenada: primero aqu´ellas cuyas filas suman 0, luego 1, luego 2, etc..
% Ejemplo: cuadradoSemiLatino(2,X). devuelve:
% X = [[0, 0], [0, 0]] ;
% X = [[0, 1], [0, 1]] ;
% X = [[0, 1], [1, 0]] ;
% X = [[1, 0], [0, 1]] ;
% X = [[1, 0], [1, 0]] ;
% X = [[0, 2], [0, 2]] ;
% etc.
% Para la implementaci´on de cuadradoSemiLatino se cuenta con el siguiente predicado:
% desde(D, D).
% desde(D, X) :- DD is D+1, desde(DD, X).

%desde(+Desde, -Numero).
desde(D, D).
desde(D, X) :- DD is D+1, desde(DD, X).

%lista_semi_latina(+Longuitud, +Suma, -Lista).
lista_semi_latina(0, 0, []).
lista_semi_latina(Long, Suma, [H | T]) :- Long > 0, Suma >= 0, Long1 is Long - 1, in_range(0, Suma, H),
NuevaSuma is Suma - H, lista_semi_latina(Long1, NuevaSuma, T).

%rectanguloSemiLatino(+Columnas, +Filas, +Suma, -XS).
rectanguloSemiLatino(_, 0, Suma, []) :- Suma >= 0.
rectanguloSemiLatino(Columnas, Filas, Suma, [H | T]) :- Filas > 0, Filas1 is Filas - 1, lista_semi_latina(Columnas, Suma, H),
rectanguloSemiLatino(Columnas, Filas1, Suma, T).

%cuadradoSemiLatino(+N, -XS).
cuadradoSemiLatino(N, X) :- desde(0, Suma), rectanguloSemiLatino(N, N, Suma, X).

% Ejercicio 18
% Sea la estructura Agenda, y los siguientes predicados disponibles:
% personas(+Agenda, -Personas), que tiene ´exito cuando Personas contiene toda la lista
% personas de la Agenda.
% edad(+Agenda, +Persona, -Edad), que tiene ´exito cuando la Persona tiene edad Edad
% la Agenda.
% Definir el predicado personasEnPromedio(+Agenda, +Edad, -Conjunto) que tenga ´exito cuando
% Conjunto sea una lista de Personas de la Agenda, cuyo promedio de edad sea menor a Edad.

%personas(+Agenda, -Personas).
personas(agenda(Personas), Personas).

%edad(+Agenda, +Persona, -Edad).
edad(agenda([persona(Nombre, Edad) | _]), Nombre, Edad).
edad(agenda([persona(OtroNombre, Edad) | Resto]), Nombre, Edad) :- OtroNombre \= Nombre,
edad(agenda(Resto), Nombre, Edad).
subconjuntos_personas(agenda([]), []).
subconjuntos_personas(agenda([H | T]), [H | Sub]) :- subconjuntos_personas(agenda(T), Sub).
subconjuntos_personas(agenda([_ | T]), Sub) :- subconjuntos_personas(agenda(T), Sub).

%promedio_edades(Personas, Edad).
suma_edades([persona(_, Edad)], Edad).
suma_edades([persona(_, Edad) | T], Suma) :- suma_edades(T, SumaT), Suma is SumaT + Edad.

%personasEnPromedio(+Agenda, +Edad, -Conjunto).
personasEnPromedio(Agenda, Edad, Conjunto) :- subconjuntos_personas(Agenda, Conjunto), suma_edades(Conjunto, Suma),
length(Conjunto, Cantidad), Promedio is (Suma // Cantidad), Edad > Promedio.

%caso: personasEnPromedio(agenda([persona(0, 0), persona(0, 1), persona(0, 2), persona(0, 3), persona(0, 4), persona(0, 5)]), 0, X).

% Ejercicio 19
% (opcional)
% Torres de Hanoi. Se tienen tres estacas A, B y C, y N discos de distintos tama˜nos, perforados en el
% centro. Los discos pueden apilarse en las estacas formando torres, y est´an ubicados inicialmente en
% la estaca A en orden decreciente de tama˜no. El problema consiste en mover los discos de A a C de
% tal manera que terminen ordenados como lo estaban originalmente. La tarea debe efectuarse bajo las
% siguientes restricciones:
% En cada paso s´olo un disco puede moverse de una estaca a otra.
% Nunca puede ubicarse un disco sobre otro m´as peque˜no.
% Usando Prolog, modelar y resolver el problema de las torres de Hanoi para tres estacas y N discos.
% data Estacas = a | b | c
% data Movimiento = Mover Estacas Estacas

%es_estaca(+E).
es_estaca(a).
es_estaca(b).
es_estaca(c).

%estacas_diferentes(-E1, -E2, -E3).
estacas_diferentes(a, b, c).
estacas_diferentes(a, c, b).
estacas_diferentes(b, a, c).
estacas_diferentes(b, c, a).
estacas_diferentes(c, a, b).
estacas_diferentes(c, b, a).

%hanoi_mover(+N, +Desde, +Hasta, -Movimientos).
hanoi_mover(0, Desde, Hasta, []) :- es_estaca(Desde), es_estaca(Hasta).
hanoi_mover(N, Desde, Hasta, Movimientos) :- N > 0, N1 is N - 1, estacas_diferentes(Desde, Hasta, Otra),
hanoi_mover(N1, Desde, Otra, MovsDesdeOtra),
hanoi_mover(N1, Otra, Hasta, MovsOtraHasta),
append(MovsDesdeOtra, [mov(Desde, Hasta) | MovsOtraHasta], Movimientos).

%hanoi(+N, -Movimientos).
hanoi(N, Movimientos) :- hanoi_mover(N, a, c, Movimientos).