Lógica: Funciones Varias (Paradigmas)
Funciones Varias
%repeat(-Elemento, -Lista). % Requiere: true. % Asegura: Lista es una lista que contiene solamente a Elem (cero o mas veces).
repeat(_, []). repeat(Elem, [Elem | Tail]) :- repeat(Elem, Tail).
%multi_length(-Lista_de_Listas, -Lista_de_Longuitudes). % Requiere: Lista_de_Listas es una lista de listas, y Lista_de_Longuitudes es una lista de naturales. % Asegura: Lista_de_Longuitudes es una lista que contiene las longuitudes de los elementos de Lista_de_Listas.
multi_length([], []). multi_length([X | XS], [L | LS]) :- length(X, L), multi_length(XS, LS).
%multi_append(-Lista_de_Listas, -Listas_Unidas). % Requiere: Lista_de_Listas no contiene ninguna lista vacia, pero ella si puede ser la lista vacia. % Asegura: Listas_Unidas son todas las listas de la listas unidas, % en el orden en que aparecian en la lista de listas.
multi_append([], []). multi_append([[X] | YS], [X | ZS]) :- multi_append(YS, ZS). multi_append([[X1, X2 | XS] | YS], [X1 | ZS]) :- multi_append([[X2 | XS] | YS], ZS).
%particion_doble(-Parte1, -Parte2, -Lista). % Requiere: true. % Asegura: Parte1 y Parte2 son una particion de Lista en dos listas, % preservando en ellas el orden relativo original de los elementos.
particion_doble([], [], []). particion_doble([X | XS], [], [X | XS]). particion_doble([], [Y | YS], [Y | YS]). particion_doble([X | XS], [Y | YS], [X | ZS]) :- particion_doble(XS, [Y | YS], ZS). particion_doble([X | XS], [Y | YS], [Y | ZS]) :- particion_doble([X | XS], YS, ZS).
%particion_doble_sin_vacio(-Parte1, -Parte2, -Lista). % Requiere: true. % Asegura: Parte1 y Parte2 son una particion de Lista en dos listas (ninguna vacia), % preservando en ellas el orden relativo original de los elementos.
particion_doble_sin_vacio([X], [Y | YS], [X, Y | YS]). particion_doble_sin_vacio([X1, X2 | XS], [Y | YS], [X1 | ZS]) :- particion_doble_sin_vacio([X2 | XS], [Y | YS], ZS). particion_doble_sin_vacio([X1, X2 | XS], [Y | YS], [X1 | ZS]) :- particion_doble_sin_vacio([Y | YS], [X2 | XS], ZS).
%particion(-ListaDeSublistas, +Lista). % Requiere: Lista es una Lista, ListaDeSublistas una lista de listas. % Asegura: ListaDeSublistas es una lista de sublistas disjuntas que forman Lista.
particion([], []). particion( XS, [X | XS]). particion([[X | XS], Y | YS], ZS) :- particion_doble_sin_vacio([X | XS], PS, ZS).
%particion_de_longuitud_n(+Lista, +Longuitud, -ListaDeSublistas)
% Requiere: Lista es una Lista de longuitud multiplo de Longuitud, ListaDeSublistas una lista de listas.
% Asegura: ListaDeSublistas es una lista de sublistas disjuntas que forman Lista cada una de longuitud Longuitud.
particion_de_longuitud_n(Lista, Longuitud, ListaDeSublistas) :- particion(ListaDeSublistas, Lista), length(Lista, Length_Lista), Cantidad is Length_Lista // Longuitud, repeat(Longuitud, Lista_Longs), length(Lista_Longs, Cantidad), multi_length(ListaDeSublistas, Lista_Longs).
%lista_de_grupos(+Lista_de_Paises_en_Grupos, +Ids, -Grupos).
lista_de_grupos([], [], []). lista_de_grupos([P | PS], [I | IS], [grupo(I, P) | GS]) :- lista_de_grupos(PS, IS, GS).
% Requiere: length(Lista_de_Paises_en_Grupos) == length(Ids). % Asegura: Grupos es la formacion de grupos asignando un id a cada grupo de paises de la lista.
%mesclar_particiones_de_listas(-Particiones, +Listas_de_Listas).
grupos(Ps, Ids, Grupos) :- lista_de_grupos(Lista_de_Paises_en_Grupos, Ids, Grupos).
%grupos(+Ps, +Ids, -Grupos)
grupos(Ps, Ids, Grupos) :- lista_de_grupos(Lista_de_Paises_en_Grupos, Ids, Grupos).
paises([[argentina, brasil], [mejico,canada], [sudafrica, egipto]]). listas([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]). listas2([1, 2, 3]).
Funciones de Numeros
%es_natural(-Numero).
es_natural(0). es_natural(N) :- es_natural(N1), N is N1 + 1.
%es_positivo(-Numero).
es_positivo(1). es_positivo(N) :- es_natural(N1), N is N1 + 1.
%es_negativo(-Numero).
es_negativo(-1). es_negativo(N) :- es_negativo(N1), N is N1 - 1.
%diferencia_con_siguiente_entero(-Signo, +Numero).
diferencia_con_siguiente_entero(1, 0). diferencia_con_siguiente_entero(1, N) :- N > 0. diferencia_con_siguiente_entero(0, N) :- N < 0.
%es_entero(-Signo, +Numero).
es_entero(0). es_entero(N) :- es_entero(M), NM is -M, diferencia_con_siguiente_entero(S, NM), N is NM + S.
%signo_aux(-Signo, +Numero).
signo_aux(0, 0). signo_aux(1, N) :- N > 0. signo_aux(-1, N) :- N < 0.
%signo(-Signo, -Numero).
signo(0, 0). signo(S, N) :- es_entero(N), N \= 0, signo_aux(S, N).
%en_rango(-Numero, +Desde, +Hasta).
en_rango(D, D, H) :- D =< H. en_rango(N, D, H) :- D =< H, ND is D + 1, en_rango(N, ND, H).
%desde(-Numero, +Desde).
desde(D, D). desde(N, D) :- DD is D+1, desde(N, DD).
Funciones de Arboles
%es_arbol_de_altura(-Arbol, +Altura).
es_arbol_de_altura(nil, 0). es_arbol_de_altura(bin(I, _, D), H) :- H > 0, H1 is H - 1, en_rango(HI, 0, H1), en_rango(HD, 0, H1), H1 is max(HD, HI), es_arbol_de_altura(I, HI), es_arbol_de_altura(D, HD).
%altura(-Arbol, -Altura).
altura(A, H) :- es_natural(H), es_arbol_de_altura(A, H).
%preorder_de_arboles(-Nodos, -Arbol).
preorder_de_arboles([], []). preorder_de_arboles(L, [nil | AS]) :- preorder_de_arboles(L, AS). preorder_de_arboles([X | XS], [bin(I, X, D) | AS]) :- preorder_de_arboles(XS, [I, D | AS]).
%preorder(-Nodos, -Arbol).
preorder(L, A) :- preorder_de_arboles(L, [A]).
Funciones de Listas
% map_tomar_uno_de_lista(-Reordenado, -Resto, +ListaDeListas) % Requiere: true. % Asegura: Reordenado es una lista formada agarrando un elemento de cada sublista % de ListaDeListas y Resto es lo que queda despues de sacar eso. % Uso:
map_tomar_uno_de_lista([], [], []). map_tomar_uno_de_lista([H | T], [R | RS], [L | LS]) :- particion_doble_unicas_vacia([H], R, L), map_tomar_uno_de_lista(T, RS, LS).
% particion(-ListaDeSublistas, +Lista). % Requiere: true. % Asegura: ListaDeSublistas es una lista de sublistas disjuntas que forman Lista. % particion( XS, [X | XS]). % particion([[X | XS], Y | YS], ZS) :- particion_doble_unicas([X | XS], WS, ZS), particion(Y | YS, WS).
% particion_doble_unicas(-Parte1, -Parte2, -Lista). % Requiere: true. % Asegura: Parte1 y Parte2 son una particion de Lista en dos listas (ninguna vacia), % preservando en ellas el orden relativo original de los elementos.
particion_doble_unicas([X], [Y | YS], [X, Y | YS]). particion_doble_unicas([X1, X2 | XS], [Y | YS], [X1 | ZS]) :- particion_doble_unicas([X2 | XS], [Y | YS], ZS). particion_doble_unicas([X1, X2 | XS], [Y | YS], [X1 | ZS]) :- particion_doble_unicas([Y | YS], [X2 | XS], ZS).
% particiones_de_longuitud_n(-ListaDeSublistas, +Longuitud, +Lista) % Requiere: true. % Asegura: ListaDeSublistas es una lista de sublistas disjuntas que forman Lista cada una de longuitud Longuitud.
particiones_de_longuitud_n([XS], L, XS) :- length(XS, L). particiones_de_longuitud_n([X | XS], L, ZS) :- not(length(ZS, L)), particion_doble_unicas(X, YS, ZS), length(X, L), particiones_de_longuitud_n(XS, L, YS).
% map_particiones_de_longuitud_n(-Sublistas, +CantidadDeGrupos, +Listas) % Requiere: true. % Asegura: similar a Haskell: map particiones_de_longuitud_n.
map_particiones_de_longuitud_n([], N, []) :- N > 0. map_particiones_de_longuitud_n([X | XS], N, [Y | YS]) :- map_particiones_de_longuitud_n(XS, N, YS), particiones_de_longuitud_n(X, N, Y).
% iesimos_elementos(-Iesimos, +Indice, -ListaDeListas) % Requiere: true. % Asegura: Iesimos son los iesimos elementos de cada lista de ListaDeListas.
iesimos_elementos([], N, []) :- N >= 0. iesimos_elementos([E | XS], I, [Y | YS]) :- nth0(I, Y, E), iesimos_elementos(XS, I, YS).
% generar_listas_tomando_de_listas_entre_iesimos(-Reordenado, +Desde, +Hasta, +ListaDeListas)
generar_listas_tomando_de_listas_entre_iesimos([], D, H, L) :- D > H, is_list(L). generar_listas_tomando_de_listas_entre_iesimos([X | XS], D, H, YS) :- D =< H, D1 is D + 1, iesimos_elementos(X, D, YS), generar_listas_tomando_de_listas_entre_iesimos(XS, D1, H, YS).
% last(+N, -Tail, -Lista). % Requiere: true. % Asegura: Tail son los ultimos n elementos de Lista.
last(N, Tail, Lista) :- length(Tail, N), append(_, Tail, Lista).
% sin_iesimo(-ListaSinIesimo, -Indice, -Lista) % Requiere: true % Asegura: ListaSinIesimo es la lista sin el elemento en la posicion Indice de Lista.
sin_iesimo(NL, I, L) :- append(Init, [_ | Tail], L), length(Init, I), append(Init, Tail, NL).
% sin_primera_aparicion(-ListaSinElemento, -Elemento, -Lista) % Requiere: true. % Asegura: ListaSinElemento es igual a Lista sin la primera aparicion del elemento.
sin_primera_aparicion(ZS, E, L) :- append(ZS1, [E | ZS2], L), append(ZS1, ZS2, ZS), not(member(E, ZS1)).
% concat(-Lista_de_Listas, -Listas_Unidas). % Requiere: true. % Asegura: Listas_Unidas son todas las listas de la listas unidas, % en el orden en que aparecian en la lista de listas.
concat([], []). concat([[X] | YS], [X | ZS]) :- concat(YS, ZS). concat([[X1, X2 | XS] | YS], [X1 | ZS]) :- concat([[X2 | XS] | YS], ZS).
% map_concat(-ListaDeListasDeListas, +ListasMappeadas) % Requiere: true. % Asegura: similar a Haskell: map concat
map_concat([], []). map_concat([X | XS], [Y | YS]) :- concat(X, Y), map_concat(XS, YS).
% take(+N, -Tail, -Lista). % Requiere: true. % Asegura: Tail son los elementos que quedan luego de sacar los n primeros % elementos a Lista.
drop(N, Tail, Lista) :- length(Init, N), append(Init, Tail, Lista).
% pertenece(-Elemento, -Lista) % Requiere: true % Asegura: Elemento pertenece a Lista.
pertenece(E, L) :- append(_, [E | _], L).
% sin_un_elemento(-ListaSinElemento, -Elemento, -Lista) % Requiere: true. % Asegura: ListaSinElemento es igual a Lista sin una vez ese elemento.
sin_un_elemento(ZS, E, L) :- append(ZS1, [E | ZS2], L), append(ZS1, ZS2, ZS).
% sin_elemento(-ListaSinElementos, +Elemento, +Lista) % Requiere: true. % Asegura: ListaSinElementos es igual a Lista sin todas las apariciones del elemento.
sin_elemento([], _, []). sin_elemento(L, H, [H | T]) :- sin_elemento(L, H, T). sin_elemento([H | L], E, [H | T]) :- E \= H, sin_elemento(L, E, T).
% iesimo(-Elemento, -Indice, -Lista) % Requiere: true % Asegura: Elemento es el elemento en la posicion Indice de Lista.
iesimo(E, I, L) :- append(Init, [E | _], L), length(Init, I).
% interseccion(-Interseccion, +ListaL, +ListaR) % Requiere: true. % Asegura: Interseccion es la interseccion sin duplicados de ListaL y ListaR % manteniendo el orden de los elementos en ListaL.
interseccion([], [], []). interseccion([E | ZS], [E | LL], LRE) :- member(E, LRE), delete(LRE, E, LR), interseccion(ZS, LL, LR). interseccion(ZS, [E | LL], LR) :- not(member(E, LR)), interseccion(ZS, LL, LR).
% sin_repetidos(-ListaSinRepetidos, +Lista). % Requiere: true. % Asegura: ListaSinRepetidos es igual a Lista solo que no tiene repetidos.
sin_repetidos([], []). sin_repetidos([E | XS], [E | YS]) :- not(member(E, YS)), sin_repetidos(XS, YS). sin_repetidos(XS, [E | YS]) :- member(E, YS), sin_repetidos(XS, YS). sin_repetidos([E | XS], [E | YS]) :- member(E, YS), sin_repetidos(XSE, YS), select(E, XSE, XS).