my game is about picking the max set of elements from a given list that their sum is N
example : L=[1,1,2,2,3,2,4,5,6]
, N = 6
, Sub List would be equal to [1,1,2,2]
I need a hint using constraint logic programming.
my game is about picking the max set of elements from a given list that their sum is N
example : L=[1,1,2,2,3,2,4,5,6]
, N = 6
, Sub List would be equal to [1,1,2,2]
I need a hint using constraint logic programming.
There is a library for Constrained Logic Programming in SWI-Prolog. It's called clpfd
.
:-use_module(library(clpfd)).
Let's say that you'll have a variable for the length of the subsequence. Its domain goes from zero (corresponding to the empty subsequence) to the length of the list. In order to get the longest sequence first, values should be tried starting with the highest.
...
length(List, M),
L in 0..M,
labeling([max(L)],[L]),
...
Next, L
can be used to build a list of L
variables that would correspond to indices of elements from List
. As these indices must be in ascending order, chain/2
can be used to create #</2
constraints between any two consecutive indices.
...
length(Indices, L),
Indices ins 1..M,
chain(Indices, #<),
...
Using these indices, a list with elements from List
can be constructed. nth1/3
is useful here, but with a minor trick.
...
nth1a(List, N, E):-
nth1(N, List, E).
...
maplist(nth1a(List), Indices, SubSequence),
...
And the sum of that list must be N
:
...
sum(SubSequence, #=, N)
...
As only the longest sequence is needed, once/1
can be used to stop after first solution is found.
Some example queries:
?- longest_subsequence([1,1,4,4,6], 9, S).
S = [1, 4, 4].
?- longest_subsequence([1,1,4,4,6], 11, S).
S = [1, 4, 6].
?- longest_subsequence([1,1,4,4,6], 21, S).
false.
As I am not sure if that's a homework or not, I won't post the full code here.
In this answer we use clpfd and a little lambda:
:- use_module([library(clpfd),
library(lambda)]).
Based on meta-predicate maplist/4
and the constraints (ins)/2
and sum/3
we define:
zs_selection_len_sum(Zs, Bs, L, S) :-
same_length(Zs, Bs),
Bs ins 0..1,
maplist(\Z^B^X^(X #= Z*B), Zs, Bs, Xs),
sum(Bs, #=, L),
sum(Xs, #=, S).
Sample queries using labeling/2
with option max/1
:
?- zs_selection_len_sum([1,1,4,4,6],Bs,L,8), labeling([max(L)],Bs). Bs = [1,1,0,0,1], L = 3 ; Bs = [0,0,1,1,0], L = 2 ; false. ?- zs_selection_len_sum([1,1,3,4,5],Bs,L,7), labeling([max(L)],Bs). Bs = [1,1,0,0,1], L = 3 ; Bs = [0,0,1,1,0], L = 2 ; false. ?- zs_selection_len_sum([1,1,2,2,3,2,4,5,6],Bs,L,6), labeling([max(L)],Bs). Bs = [1,1,0,1,0,1,0,0,0], L = 4 ; Bs = [1,1,1,0,0,1,0,0,0], L = 4 ; Bs = [1,1,1,1,0,0,0,0,0], L = 4 ; Bs = [0,0,1,1,0,1,0,0,0], L = 3 ; Bs = [0,1,0,0,1,1,0,0,0], L = 3 ; Bs = [0,1,0,1,1,0,0,0,0], L = 3 ; Bs = [0,1,1,0,1,0,0,0,0], L = 3 ; Bs = [1,0,0,0,1,1,0,0,0], L = 3 ; Bs = [1,0,0,1,1,0,0,0,0], L = 3 ; Bs = [1,0,1,0,1,0,0,0,0], L = 3 ; Bs = [1,1,0,0,0,0,1,0,0], L = 3 ; Bs = [0,0,0,0,0,1,1,0,0], L = 2 ; Bs = [0,0,0,1,0,0,1,0,0], L = 2 ; Bs = [0,0,1,0,0,0,1,0,0], L = 2 ; Bs = [0,1,0,0,0,0,0,1,0], L = 2 ; Bs = [1,0,0,0,0,0,0,1,0], L = 2 ; Bs = [0,0,0,0,0,0,0,0,1], L = 1 ; false.