factorial(0, 1). factorial(N, F):- N > 0, N1 is N - 1, factorial(N1, F1), F is N * F1. nod(a). nod(b). nod(c). nod(d). nod(e). nod(f). nod(g). nod(h). nod(i). nod(j). nod(k). nod(l). nod(m). nod(n). nod(p). nod(o). arc(a,b). arc(a,c). arc(b,d). arc(c,e). arc(c,g). arc(e,f). arc(h,i). arc(h,j). arc(i,k). arc(j,l). arc(n,o). arc(o,p). %% descendantOf/2 %% descendantOf(?X, ?Y) %% Nodul X este un urmaș a lui Y. %% Hint: Predicatul este adevărat dacă există un arc de la Y la X sau %% dacă există arc de la unul dintre urmașii lui Y la X. descendantOf(X, Y) :- arc(Y, X). descendantOf(X, Y) :- arc(Y, Z), descendantOf(X, Z). % cazurile mai particulare mai înainte. % condițiile care restricționeză cât mai în față (cât mai spre stânga) % apelul recursiv mai la sfârșit în condiții. % findall cu construcție de template care este mai mult decât o singură variabilă: % ?- findall((X, SqX), (member(X, [1,2,3,4]), SqX is X*X), Bag). % Bag = [(1, 1), (2, 4), (3, 9), (4, 16)] % 2. Cheryl's Birthday % ==================================================== % Albert and Bernard have just met Cheryl. 'When is your birthday?' % Albert asked Cheryl. Cheryl thought for a moment and said, 'I won't % tell you, but I'll give you some clues'. She wrote down a list of ten % dates: % May 15, May 16, May 19 % June 17, June 18 % July 14, July 16 % August 14, August 15, August 17 % 'One of these is my birthday,' she said. % Cheryl whispered in Albert's ear the month, and only the month, of her % birthday. To Bernard, she whispered the day, and only the day. 'Can % you figure it out now?' she asked Albert. % Albert: 'I don't know when your birthday is, but I know Bernard % doesn't know, either.' % Bernard: 'I didn't know originally, but now I do.' % Albert: 'Well, now I know, too!' % When is Cheryl's birthday? dates([may/15, may/16, may/19, june/17, june/18, july/14, july/16, aug/14, aug/15, aug/17]). % Date - data completa - Day/Month % Day - ziua calendaristica (numarul) % Month - luna % daysIn(+Month, -Days) % Care sunt zilele (Days) pentru datele din dates care au luna Month? daysIn(Month, Days) :- dates(Dates), % findall( % D, % ( member(M/D, Dates), % M == Month % ), Days). findall(D, member(Month/D, Dates), Days). % monthsWith(+Day, -Months) % Care sunt lunile (Months) pentru datele din dates care au ziua Day? monthsWith(Day, Months) :- dates(Dates), findall(M, member(M/Day, Dates), Months). % Verificăm că într-adevăr Albert nu știe. albert1a(Dates) :- % este adevărat pentru toate datele din Dates că dacă ne uităm la luna (M) din dată... forall(member(M/_, Dates), % sunt cel puțin două date care sunt în luna respectivă. daysIn(M, [_,_|_])) % sau % ( daysIn(M, Days), length(Days, N), N>1)) . % Albert spune: "dar nici Bernard nu știe" albert1b(DatesIn, DatesOut) :- % filtrăm din DatesIn acele date Date... findall(Date, ( member(Date, DatesIn), Date = Month/_, % ale căror lună (Month)... daysIn(Month, DaysInMonth), % conține doar zile (D)... forall(member(D, DaysInMonth), % care nu sunt singure în tabel (sunt mai multe date cu ziua respectivă). monthsWith(D, [_, _|_])) ), % cu debugging: % format("here days ~w ~w~n", [Month, DaysInMonth]), % forall((member(D, DaysInMonth), format("pentru ~w ", % [D])), % ( monthsWith(D, [_, _|_]), format("am gasit % ~n"))) DatesOut). % Bernard spune că acum știe bernard1(DatesIn, DatesOut) :- % filtrăm din DatesIn acele date Date... findall(Date, ( member(Date, DatesIn), Date = _/Day, % ale căror zi (Day)... % apare în datele din DatesIn o singură dată % (există o singură dată în DatesIn cu acea zi). findall(_, member(_/Day, DatesIn), [_]) % sau % findall(Date1, ( % member(Date1, DatesIn), % Date1 = _/Day % iterez peste 14, 16 iunie si 14, 15, 17 aug % daca data are aceeasi zi cu cea pe care o stie bernard (cu data din solutie) % ), [_]) ), DatesOut). % Alber spune că și el acum știe albert2(DatesIn, DatesOut) :- % filtrăm din DatesIn acele date Date... findall(Date, ( member(Date, DatesIn), % ale căror lună (Month)... Date = Month/_, % apare în datele din DatesIn o singură dată % (există o singură dată în DatesIn cu acea zi) findall(_, member(Month/_, DatesIn), [_]) ), DatesOut). sol(Date) :- dates(Dates0), albert1a(Dates0), albert1b(Dates0, Dates1), bernard1(Dates1, Dates2), albert2(Dates2, Dates3), % Dates = Dates3 Dates3 = [Date] . % ALT MOD DE A CONSTRUI SOLUȚIA % Albert: I don't know s1a(Day, Month) :- % soluția este o dată zi-lună dates(Dates), member(Month/Day, Dates), % din mulțimea de date daysIn(Month, [_, _|_]). % în care luna are mai multe zile candidați % Albert: Bernard doesn't know s1b(Day, Month) :- % soluția este o dată zi-lună s1a(Day, Month), % care respectă prima afirmație daysIn(Month, Days), % și dintre zilele candidați din luna respectivă findall(D, % nu există nicio zi D ( member(D, Days), % dintre zilele din luna datei monthsWith(D, [_]) % care să indice unic o anumită luna ), []). % (nicio soluție) % Bernard: now I know s2(Day, Month) :- % soluția este o dată zi-lună s1b(Day, Month), % care respectă afirmațiile de mai sus monthsWith(Day, Ms), % și dintre lunile care conțin ziua respectivă findall(M, % există o singură lună ( member(M, Ms), % dintre lunile care conțin ziua s1b(Day, M)), % care respectă afirmațiile de mai sus [_]). % (o singură soluție) % Albert: now I know too s3(Day, Month) :- % soluția este o dată zi-lună s2(Day, Month), % care respectă afirmațiile de mai sus daysIn(Month, Days), % și dintre zilele din luna respectivă findall(D, % există o singură zi ( member(D, Days), % dintre zilele din lună s2(D, Month)), % care respectă afirmațiile de mai sus [_]). % (o singură soluție) sol2(Month/Day) :- s3(Day, Month). % soluția este o dată care respectă toate afirmațiile % TEST: % scrieti un predicat filterP(LIn, LOut) unde in LOut se pastreaza doar % acele elemente din LIn pentru care predicatul p este adevarat. % Folositi findall. Explicati cum functioneaza. p(X) :- X > 5. filter(LIn, Lout) :- findall(X, (member(X, LIn), p(X)), Lout).