定义一个谓词子集(L,Sum,Subl),它取一个数字列表L,一个数字Sum,并用一个子序列L统一SubL,使得SubL中的数字之和为Sum。
例如
?- subsetsum([1,2,5,3,2], 5, SubSet);
SubSet = [1,2,2];
SubSet = [2,3];
SubSet = [5];
SubSet = [3,2];
No.
我们有
sum([H1 | [H2 | Tail]], S):-
sum([[H1+H2]|Tail], S):-
sum([X], X).
和
subset([],[]).
subset([H1|T1], [H1|T2]) :- // heads are the same
subset(T1, T2).
subset([_|Rest], X):
subset(Rest, X).
答案 0 :(得分:2)
如果使用的所有数字都是整数且Prolog处理器支持clpfd,请按以下步骤操作!
:- use_module(library(clpfd)). z_z_product(A,B,AB) :- AB #= A*B. subsetsum_(Zs, Sum, Bs, [Sum|Vs]) :- same_length(Zs, Bs), append(Zs, Bs, Vs), Bs ins 0..1, maplist(z_z_product, Zs, Bs, Xs), sum(Xs, #=, Sum).
示例查询:
?- subsetsum_([1,2,5,3,2], 5, Sel, Vs), labeling([], Vs). Sel = [0,0,0,1,1], Vs = [5,1,2,5,3,2,0,0,0,1,1] ; Sel = [0,0,1,0,0], Vs = [5,1,2,5,3,2,0,0,1,0,0] ; Sel = [0,1,0,1,0], Vs = [5,1,2,5,3,2,0,1,0,1,0] ; Sel = [1,1,0,0,1], Vs = [5,1,2,5,3,2,1,1,0,0,1] ; false.
答案 1 :(得分:1)
以下条款应该做你需要的......
subsetsum(SET, SUM, ANSWER) :-
% Find a subset
subset(SET, ANSWER),
% Check elements of the subset add up to SUM
sum(ANSWER, SUM).
% sum(LIST, SUM) - sums all numbers in the list
sum([], 0).
sum([X | T], SUM) :-
sum(T, TAILSUM),
SUM is TAILSUM + X.
% subset - finds subsets
subset([], []).
subset([E|Tail], [E|NTail]) :-
subset(Tail, NTail).
subset([_|Tail], NTail) :-
subset(Tail, NTail).
答案 2 :(得分:1)
使用swi-prolog,我们可以将库谓词sum_list/2
与您已经拥有的subset/2
一起使用!请注意,我为subset/2
提供了更合适的名称list_subsequence/2
:
list_subsequence([], []). list_subsequence([X|Xs], [X|Ys]) :- list_subsequence(Xs, Ys). list_subsequence([_|Xs], Ys) :- list_subsequence(Xs, Ys). subsetsum(List, Sum, Sub) :- list_subsequence(List, Sub), sum_list(Sub, Sum).
以下是您提供的示例查询:
?- subsetsum([1,2,5,3,2], 5, Xs).
Xs = [1,2,2]
; Xs = [2,3]
; Xs = [5]
; Xs = [3,2]
; false.
好的!让我们用整数和浮点运行另一个查询......这样做也有效吗?
?- subsetsum([1,2.1,5,3,2], 5.1, Xs). Xs = [1,2.1,2] ; Xs = [2.1,3] ; false.
对我来说没问题!