solution/3 — sublistă de pare sau impare cu constrângeri
Scrieți un predicat solution/3 care primește o listă de elemente întregi, o sumă S și returnează, în al treilea argument, o sublistă Sol astfel încât:
- suma elementelor din sublista
Solsă fie egală cuS Soleste o sublistă de numerele pare consecutive sau o sublistă de numere impare consecutive din lista inițială; de exemplu în lista[1, 2, 3, 5, 4]elementele2și4sunt numere pare consecutive, iar1, 3, 5sunt numere impare consecutive- dacă
Solconține numere pare atunci cu siguranță există și o listă de numere impare cu sumaS, de lungime ≤ cu lungimea luiSol - dacă
Solconține numere impare atunci cu siguranță există și o listă de numere pare cu sumaS, de lungime < cu lungimea luiSol - predicatul eșuează dacă nu există liste cu numere pare și liste cu numere impare consecutive care au suma
S
?- solution([3,2,1,4,5,6], 6, Sol).
Sol = [2, 4]
% se putea obține și din [1, 5], și din [2, 4], dar s-a preferat lista elementelor pare
?- solution([1, 1,2,1,6,5,6], 8, Sol).
Sol = [1, 1, 1, 5]
% se putea obține 8 și din [2, 6], dar s-a preferat cea mai lungă dintre subliste
?- solution([1, 1,2,1,6,5,6], 12, Sol).
false
% se poate obține 12 din [6, 6], dar pe impare nu se poate obține, deci false conform condiției 5
Hint: separă lista în lista pare-consecutive și lista impare-consecutive. Găsește toate sublistele contigue ale fiecăreia care au suma
S. Dacă ambele mulțimi sunt nevide, aplică regulile 3 și 4 (în esență: preferă cea mai lungă, cu tiebreaker pe pare).
Te-ai blocat?
editor
soluție
% filtrează pare și impare păstrând ordinea
evens([], []).
evens([H | T], [H | E]) :- H mod 2 =:= 0, !, evens(T, E).
evens([_ | T], E) :- evens(T, E).
odds([], []).
odds([H | T], [H | O]) :- H mod 2 =:= 1, !, odds(T, O).
odds([_ | T], O) :- odds(T, O).
% suma elementelor
list_sum([], 0) :- !.
list_sum([H | T], S) :- list_sum(T, ST), S is ST + H.
% sublistă contiguă nevidă
contig(L, Sub) :-
append(_, Rest, L),
append(Sub, _, Rest),
Sub \= [].
% maximul dintre două numere
max2(A, B, A) :- A >= B, !.
max2(_, B, B).
% cea mai lungă sublistă dintr-o listă de liste
longest_len([], 0).
longest_len([L | Rest], M) :-
longest_len(Rest, RM),
length(L, LL),
max2(LL, RM, M).
solution(L, S, Sol) :-
evens(L, Es),
odds(L, Os),
findall(Sub, (contig(Es, Sub), list_sum(Sub, S)), EvenSols),
findall(Sub, (contig(Os, Sub), list_sum(Sub, S)), OddSols),
EvenSols \= [],
OddSols \= [],
longest_len(EvenSols, EL),
longest_len(OddSols, OL),
% preferă pare la egalitate; imparele câștigă doar strict
( EL >= OL
-> member(Sol, EvenSols), length(Sol, EL), !
; member(Sol, OddSols), length(Sol, OL), !
).
?-
Tastează o interogare (ex. father_of(sandra, X).) și apasă Enter — sau apasă pe un caz de test de mai jos.
Cazuri de test (3 — apasă pe unul ca să îl rulezi, sau Verifică pentru toate)
?
solution([3,2,1,4,5,6], 6, Sol).
așteptat: Sol = [2,4]
?
solution([1,1,2,1,6,5,6], 8, Sol).
așteptat: Sol = [1,1,1,5]
?
solution([1,1,2,1,6,5,6], 12, Sol).
așteptat: false