'Output is a list of three elements [A,B,C] taken from items that together add up to goal. The Output inside the items list in that order
`three Sum([1,2,3,4,5,6,7,8,9],12,Output).
Output=[1,2,9];
Output=[1,3,8];
Output=[1,4,7];
Output=[1,5,6];
Output=[2,3,7];
Output=[2,4,6];
Output=[3,4,5]`
we should make result = summation 3 elements sorted ascendingly from list
Solution 1:[1]
This is fundamentally a matter of finding all the combinations of n
things taken k
at a time. To do that is pretty simple:
combination( 0 , _ , [] ) :- !.
combination( N , L , [C|Cs] ) :-
N > 0,
N1 is N-1,
select(L,C,L1),
combination(N1, L1, Cs).
select( [H|T] , H, T ) .
select( [_|T] , H, R ) :- select(T,H,R) .
once you have that, then it is a matter of wrapping it up nicely:
combination_sum( Xs, K, V, Ys ) :-
sort(Xs,X0), % orders the list, making it a proper set by removing duplicates
length(Xs,L),
between(1,L,K), % ensures K has a sensible value (and allows K to be unbound
combination(K,X0,Ys),
sum_of(Ys,V).
sum_of( Xs , S ) :- sum_of(Xs,0,S).
sum_of( [] , S , S ).
sum_of( [X|Xs] , T , S ) :- T1 is T+X, sum_of(Xs,T1,S) .
That gives you the generic, flexible solution: you can solve the problem for any given sized subset.
Note also that you may, should you choose, leave K
or V
unbound (or both, for that matter), and it will return all solutions for the given constraints:
combination_sum( [1..n], K, V, L )
yields all combinations of any length and their sumcombination_sum( [1..n], K, 12, L )
yields all combinations of any length that sum to 12.combination_sum( [1..n], 3, V, L )
yields all combinations of length 3 that sum to any value.combination_sum( [1...n], 3, 12, L )
yields all combinations of length 3 that sum to 12.
Then, just wrap that for your specialized use case:
sum_three(Xs,V,Ys) :- combination_sum(Xs,3,V,Ys).
Solution 2:[2]
three_sum(Lst, Total, [One, Two, Three]) :-
% Using msort, to sort without removing duplicates
msort(Lst, LstSorted),
select_remainder(One, LstSorted, Lst1),
select_remainder(Two, Lst1, Lst2),
select_remainder(Three, Lst2, _),
Total is One + Two + Three.
select_remainder(Elem, [H|T], RemainderForward) :-
select_remainder_(T, H, Elem, RemainderForward).
select_remainder_(T, H, H, T).
select_remainder_([H|T], _, Elem, R) :-
select_remainder_(T, H, Elem, R).
Result in swi-prolog:
?- time(findall(Lst, three_sum([1,2,3,4,5,6,7,8,9], 12, Lst), Lsts)).
% 278 inferences, 0.000 CPU in 0.000 seconds (93% CPU, 1220471 Lips)
Lsts = [[1,2,9],[1,3,8],[1,4,7],[1,5,6],[2,3,7],[2,4,6],[3,4,5]].
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |