% Progress → % valori de prim rang în Prolog -- predicate/valori booleene vs argumente/diverse tipuri/liste/structuri % ideea de relație între concepte % exemplu cu Alice: ce concepte sunt? (lion, unicorn, days), ce relații sunt (yesterday, lies, saysLies) % Manual Prolog % http://www.swi-prolog.org/pldoc/doc_for?object=manual % http://www.swi-prolog.org/pldoc/man?section=builtin % programul: descrie ce este adevărat, eventual în funcție de condiții. p(1). p(2). p(a). p([1,2,3]). q(X, X) :- p(X). t(X) :- \+ p(X). % nu va găsi soluții singur. % putem pune predicatul să găsească soluții dacă avem un domeniu. s(X) :- member(X, [1, 2, 3, 4, 5, a, b, c, d, e, [1], [1, 2], [1, 2, 3]]), \+ p(X). % Alice came across a lion and a unicorn in a forest of forgetfulness. % Those two are strange beings. % The lion lies every Monday, Tuesday and Wednesday % and the other days he speaks the truth. % The unicorn lies on Thursdays, Fridays and Saturdays, % however the other days of the week he speaks the truth. % Lion: Yesterday I was lying. % Unicorn: So was I. % Which day did they say that? days([mon, tue, wed, thu, fri, sat, sun]). is_next(Y, T, [Y, T|_]). is_next(Y, T, [_|Days]) :- is_next(Y, T, Days). yesterday(T, Y) :- days(Days), (is_next(Y, T, Days) ; Days = [T|_], reverse(Days, [Y|_])). yesterday(mon, sun). yesterday(tue, mon). yesterday(wed, tue). yesterday(thu, wed). yesterday(fri, thu). yesterday(sat, fri). yesterday(sun, sat). lies(lion, [mon, tue, wed]). lies(unicorn, [thu, fri, sat]). % Animal spune azi (Today) ca ieri a mintit saysItLiedYesterday(Animal, Today) :- yesterday(Today, Yesterday), lies(Animal, DaysLies), % obtine DaysLies \+ member(Today, DaysLies), % azi minte member(Yesterday, DaysLies). saysItLiedYesterday(Animal, Today) :- yesterday(Today, Yesterday), lies(Animal, DaysLies), member(Today, DaysLies), \+ member(Yesterday, DaysLies). % solutia sol(Today) :- saysItLiedYesterday(lion, Today), saysItLiedYesterday(unicorn, Today). % 0. o funcție simplă pe liste % ========================================== % myMember(+Elem, +Lista) myMember(_, []) :- fail. % lista vida nu poate contine elementul. Aceasta linie poate sa lipseasca. % myMember(E, [H|_]) :- E == H. myMember(E, [E|_]). % elementul este primul element din lista myMember(E, [H|T]) :- E \= H, myMember(E, T). % elementul nu este primul din lista. myMember2(X, [H|T]) :- X=H ; myMember2(X, T). % folosind 'sau' % 1. liste; direcția construirii soluțiilor % ========================================== % extragere elemente din listă folosind pattern-matching head([H|_], H). first_two([E1, E2 | _], E1, E2). % etc % o prelucrare simplă pe liste % sumList(+L, -Suma) sumList([], 0). sumList([H|T], S) :- sumList(T, ST), S is ST + H. inc(X, Y) :- Y is X + 1. % doresc ceva echivalent cu map (+1) list % Simplu - recursivitate pe stivă (se mai face o unificare la % întoarcere, în argumentul de ieșire). % incListS(+LI, -LO) incListS([], []). incListS([H|T], LOut) :- inc(H,H1), incListS(T,T1), LOut = [H1 | T1]. % echivalent cu % incListS([H | T],[H1 | T1]) :- inc(H, H1), incListS(T, T1). % Cu acumulator și construcția rezultatului pe avansul în recursivitate. % Recursivitate pe coada % incListT(+LI, -LO) incListT(L,LR) :- incListTH(L,[],LR). % incListTH(+LI, +Acc, -LO) incListTH([], L, LOut) :- reverse(L, LOut). incListTH([H|T], LA, LR) :- inc(H,H1), incListTH(T, [H1 | LA], LR). % 2. debugging: % ============================================== % folosire predicates trace, notrace (eventual debug și nodebug): % guitracer/0 pentru activarea debuggerului grafic % noguitracer/0 pentru dezactivare. % ?- trace, predicat(args), nodebug. % vedeți și http://www.swi-prolog.org/pldoc/man?section=debugoverview % pentru predicate de 1 argument dotracing(P, X) :- trace, call(P, X), nodebug. % 3. variabile neinstanțiate % ========================================== % any(X). any(X) :- display(X). % sau: any(X) :- format("X este: ~w~n", [X]). any(X, X). % încercați: % ?- any(X, Y). % any(X, Y) :- X = Y. % identic cu any(X, X). % any(X, Y) :- X is Y. % încercați any(X, 1+2) cu ambele variante de implementare de mai sus. % la consolă vad 'ce legări s-au forțat ca să fie adevarat?'. /* de executat la consolă: ?- any(X,Y), X = 5. X = Y, Y = 5. ?- any(X,Y), Y = 5. X = Y, Y = 5. ?- [1,2,3] = [1,2,3]. true. ?- [1,X,Y] = [1,2,3]. X = 2, Y = 3. ?- [1,X,Y] = [Z,2,3]. X = 2, Y = 3, Z = 1. ?- [1,X,Y] = Z. Z = [1, X, Y]. ?- [1,X,Y] = Z, (X,Y)=(2,3). X = 2, Y = 3, Z = [1, 2, 3]. ?- */ % 4. generarea numerelor % ========================================== % puterea generativă a limbajului: generarea unei liste % la consolă: % % ?- member(1, [1,2,3]) % ?- member(X, [1, 2, 3]). % ?- member(1, L). % ?- length(L, 3), member(1, L), member(2, L), member(3, L). /* ?- append([1,2,3], [2,3,4], L). L = [1, 2, 3, 2, 3, 4]. ?- append([1,2,3], L, [1,2,3,4,5]). L = [4, 5]. ?- 1 < 2. true. ?- abc < adb. ERROR: Arithmetic: `abc' is not a function ERROR: In: ... ?- abc @< adb. true. ?- [1,2,3] @< [1,3,4]. true. ?- [1,2,3] @< [1,2,2]. false. ?- member(X, [1,2,3,4,5]), X > 2. X = 3 ; X = 4 ; X = 5. */ % findall(template = ce pun în listă, scop, listă cu acele legări % pentru template care satisfac scopul) /* ?- findall(X, (member(X, [1,2,3,4,5]), X > 2), Bag). Bag = [3, 4, 5]. ?- findall((X, Y), (member(X, [1,2,3,4,5]), X > 2, member(Y, [a, b, c])), Bag). Bag = [(3, a), (3, b), (3, c), (4, a), (4, b), (4, c), (5, a), (5, b), (..., ...)]. ?- findall((X, Y), (member(X, [1,2,3,4,5]), X > 3, member(Y, [a, b, c])), Bag). Bag = [(4, a), (4, b), (4, c), (5, a), (5, b), (5, c)]. ?- */ % doresc o funcție interval(?X) care să îmi dea pe rând soluțiile X = 0; X = 1; ... X = 10 % interval(X) :- X =< 10. % argumente insuficient instanțiate % construim bazându-ne pe valori pentru care predicatul a fost deja % demonstrat interval(0). interval(X) :- interval(Y), Y < 10, X is Y + 1. % merge la infinit după X = 10 % evităm ca apelul recursiv să fie prima condiție interval2H(I, _, I). interval2H(I, L, X):- I < L, I1 is I + 1, interval2H(I1, L, X). interval2(X) :- interval2H(0, 10, X). % 5. cut și fail % ============================================== min(X, Y, M) :- X =< Y, M is X. min(X, Y, M) :- X > Y, M is Y. min2(X, Y, M) :- X =< Y, M = X. min2(X, Y, M) :- X > Y, M = Y. % Echivalent cu min2. min3(X, Y, X) :- X =< Y. min3(X, Y, Y) :- X > Y. % Greșit! A doua soluție nu va fi corectă. min4(X, Y, X) :- X =< Y. min4(_, Y, Y). % Corect: o singură soluție. min5(X, Y, X) :- X =< Y, !. min5(_, Y, Y). % myMem(+Elem, +Lista) myMem(_, []) :- fail. % lista vida nu poate contine elementul. Aceasta linie poate sa lipseasca. % myMem(E, [H|_]) :- E == H. % myMem(E, [E|_]). % elementul este primul element din lista myMem(E, [E|_]) :- !. myMem(E, [_|T]) :- myMem(E, T). % elementul nu este primul din lista. este(lili, liliac). este(fifi, papagal). zboara(liliac). zboara(papagal). % utilizare cut împreună cu fail pasare(X) :- este(X, liliac), !, fail. pasare(liliac) :- !, fail. pasare(X) :- este(X, Y), zboara(Y), !. pasare(X) :- zboara(X). % 6. afișare: predicatul format % ============================================== % print(_). prettyPrintList(L) :- ppListH(L, 1). ppListH([], N) :- format("completed, ~w elements printed.~n", [N]). ppListH([H|T], I) :- format("element no. ~w: ~w~n", [I, H]), I1 is I + 1, ppListH(T, I1).