我正在尝试编写一个谓词,当且仅当列表D包含列表A中的元素时,这将是真的,这些元素在列表A中的次数。例如 -
D [1,5,5,3]; A [4,6,1,0,5,3,5]
将是真的
D [1,5,5,3]; A [4,6,1,0,5,3,5,5]
将是假的,因为D只有5次,但A有5次3次。我试图这样做有意义。我的代码片段是休闲 -
sub_third(_, []) :-
true.
sub_third(D, [H|T]) :-
member(H, D) ->
select(H, D, D_new), sub_third(D_new, T) ;
false.
third(_, [], _) :-
true.
third(D, [H|T], A) :-
(\+member(H, D) ->
select(H, A, A_new), third(D, T, A_new) ;
third(D, T, A)) ->
(sub_third(D, A_new);
false).
基本上我在这里做的是通过第三个'谓词列表D和两次列表A.第一个实现我试图删除第二个A列表中的所有元素,这些元素在第一个A列表中找不到(如果H元素存在于列表D中,则用下一个T递归调用该调用元素并且不做任何更改,但是如果在D列表中找不到H,则将其从第二个A列表中删除并再次调用递归,但是使用修改后的A列表)。当没有更多T元素时,列表A应该只包含与列表D相同的元素,然后使用sub_third谓词找出,如果所有元素都是相同的计数。 Sub_third工作正常,所以我认为错误应该在影响范围内,因为我不熟悉它们。
P.S。成员函数检查元素是否是列表的成员,并且select函数接受元素和列表,然后从第一个列表中删除给定元素的第三个列表。 (这就是我在这里使用它的方式)
答案 0 :(得分:1)
您应该尝试为谓词找到更清晰的名称。即使你知道sub_third
应该是什么意思,我们也不知道。这使得理解和调整代码变得更加困难。
您使用select/3
的基本想法很好,但您没有正确分解问题。首先尝试计算列表之间的差异,然后检查它不包含任何不需要的元素的额外属性:
% list_subtract(Xs, Ys, Zs) is true if Zs is a list obtained by removing one
% occurrence of each element of Ys from Zs. False if there are elements in
% Ys that have no corresponding occurrence in Xs.
list_subtract(Xs, [], Xs).
list_subtract(Xs, [Y|Ys], Zs) :-
select(Y, Xs, Xs1),
list_subtract(Xs1, Ys, Zs).
% tests
:- list_subtract([4, 6, 1, 0, 5, 3, 5], [1, 5, 5, 3], Zs), Zs = [4, 6, 0].
:- list_subtract([4, 6, 1, 0, 5, 3, 5, 5], [1, 5, 5, 3], Zs), Zs = [4, 6, 0, 5].
% list_subtract_without_rest(Xs, Ys, Zs) is true if Ys can be subtracted
% from Xs in the sense of the list_subtract/3 predicate, and the remaining
% difference Zs does not contain any elements of Ys.
list_subtract_without_rest(Xs, Ys, Zs) :-
list_subtract(Xs, Ys, Zs),
\+ (member(Z, Zs), member(Z, Ys)).
% tests
:- list_subtract_without_rest([4, 6, 1, 0, 5, 3, 5], [1, 5, 5, 3], _).
:- \+ list_subtract_without_rest([4, 6, 1, 0, 5, 3, 5, 5], [1, 5, 5, 3], _).