/* Programma che trova il percorso di peso minimo
dalla radice alle foglie.
Il comando che lo avvia è min(P,C).
dove C sarà il costo del percorso P. */
/* camgr(A,B,L,C). trova un cammino da A a B che
memorizza nella lista L e calcola il suo costo C */
camgr(A,B,[A,B],C):-grafo(A,B,C).
camgr(A,B,[A|L],Costo):-grafo(A,D,C1),
camgr(D,B,L,C2),
Costo is C1+C2.
/* camgr2(A,B,L,C). */
camgr2(A,B,L,C):-cgr2(A,B,L,[B],C).
cgr2(A,A,L,L,0).
cgr2(A,B,L,Q,Costo):-grafo(D,B,C1),
cgr2(A,D,L,[D|Q],C2),
Costo is C1+C2.
/* totgr(A,B,R). trova tutti i cammini possibili da A a B con i
loro rispettivi costi */
totgr(A,B,R):-findall((L,C),camgr(A,B,L,C),R).
/* lungr(A,B,N). restituisce il numero di cammini esistenti da A a B */
lungr(A,B,N):-totgr(A,B,R),
cardinalita(R,N).
cardinalita([],0).
cardinalita([T|C],N):-cardinalita(C,M),
N is M+1.
/* mingr(A,B,L,C). trova il cammino L da A a B di peso minimo C */
mingr(A,B,L,C):-totgr(A,B,R),
m_gr(R,L,C).
/* m_gr(R,L,C). stabilisce quale dei cammini e di costo minore */
m_gr( [(P,Costo)|Coda] ,L,C):-minimogr(Coda,P,Costo,L,C).
minimogr([],P,C,P,C).
minimogr([(P1,C1)|Coda],P2,C2,L,C):-C2=C1,
minimogr(Coda,P1,C1,L,C).
/* ESERCIZIO: CAMMINI IN UN GRAFO
Dati due nodi, costruire in ordine casuale tutti
i cammini che li congiungono con la relativa
distanza.
Dato un grafo e due suoi nodi, trova tutti i
percorsi aciclici con rispettivo peso.
Nel caso che i nodi siano uguali, il risultato e'
una lista vuota.
Nel caso che almeno uno dei due nodi non appartenga
al grafo, il risultato è una lista vuota. */
/* Gli archi sono del tipo:
arco(<nodo>,<nodo>,<peso>) */
/* PRODOTTO SCALARE di due liste aventi cardinalita'
uguale: */
sca([T1|C1],[T2|C2],K):-sca(C1,C2,Q),
K is Q+T1*T2.
/* con controllo sulla cardinalita' */
sca2(L1,L2,R):-cardinalita(L1,N1),
cardinalita(L2,N2),
prod_scalare(L1,N1,L2,N2,R).
prod_scalare(_,N1,_,N2,R):- N1 \= N2,
write('Le due liste non hanno la stessa'),
write(' cardinalità.'),
R = nessun_valore.
prod_scalare([],0,[],0,0). /* PASSO BASE */
prod_scalare([T1|C1],N1,[T2|C2],N2,R):- N1 = N2,
M1 is N1-1,
M2 is N2-1,
prod_scalare(C1,M1,C2,M2,W),
R is W+T1*T2.
/* ALTERNATIVA (senza controllo cardinalita'):
METODO PROCEDURALE */
/* il fatto fatt(1,1). e' ridondante, quindi non e' stato inserito */
fatt(0,1):- !.
fatt(N,F):- M is N-1,
fatt(M,K),
F is N*K.
/* Sottinsieme: */
/* sott(L1,L2). stabilisce se gli elementi della prima lista
sono tutti anche elementi della seconda lista, cioe' se la
prima lista e' un 'sottoinsieme' della seconda */
sott([],_).
sott([T|C],L):- member(T,L),
sott(C,L).
member(T,[T|C]).
member(T,[T2|C]):-member(T,C).
/* attenzione_orlo(L1,L2). ha successo se la lista L1 si puo' ricavare
'orlando' la seconda.
ATTENZIONE: non usare se L1 non e' orlo di L2 perche' il calcolatore
cerca tutte i possibili modi di eseguire il primo append,
cioe' infiniti */
attenzione_orlo(L1,L2):- append(_,L1,T),
append(T,_,L2).
/* orlo(L1,L2). ha successo se la lista L1 e 'orlo' della seconda
ed ha il vantaggio che il numero di volte in cui si puo
eseguire il primo append e limitato perche' corrisponde
esattamente al numero di volte in cui si puo formare
la lista L2 giustapponendo due liste */
orlo(L1,L2):- append(X,_,L2),
append(_,L1,X).
append([],L,L).
append([T|C],L,[T|A]):-append(C,L,A).
/* la domanda ?-orlo(X,[a,b]). ha un numero limitato di risposte,
quindi il processo termina */
/* la domanda ?-attenzione_orlo(X,[a,b]). e tale per cui il processo
di risposte e' infinito */
/* MASSIMO TRA GLI ELEMENTI DI UNA LISTA */
max1([],P):- write('Lista vuota, impossibile calcolare il valore massimo'),
P = nessun_valore.
max1([T],T).
max1([T|C],M):-max(C,N),
comp_max(T,N,M),
!.
comp_max(T,N,T):- T>=N.
comp_max(T,N,N):- T<N.
max2([T|C],M):- massimo(C,T,M).
massimo([],M,M).
massimo([T|C],X,M):-maggiore(T,X,Y),
massimo(C,Y,M).
maggiore(A,B,A):- A>=B.
maggiore(A,B,B):- A<B.
/* Elimina Elementi Ripetuti in una lista
creando cosi' un Insieme */
set(L,R):-elimina(L,R,[]).
elimina([],R,R).
elimina([T|C],R,Q):- member(T,C),
elimina(C,R,Q).
elimina([T|C],R,Q):- not member(T,C),
elimina(C,R,[T|Q]).
/* DATE DUE LISTE STABILISCE SE LA PRIMA E'
UN PREFISSO DELLA SECONDA */
prefix([],_).
prefix([T|C],[T|L]):-prefix(C,L).
/* DATE DUE LISTE STABILISCE SE LA PRIMA E'
UN SUFFISSO DELLA SECONDA */
suffix(L,L).
suffix(L,[T|C]):-suffix(L,C).
/* DATE DUE LISTE STABILIRE SE LA PRIMA E' UNA SOTTOLISTA DELLA SECONDA */