检查列表是否由N个X实例组成(重复X次N次)

时间:2014-12-05 07:22:34

标签: list prolog infinite-loop

给出如下的查询:

containsN(4,2,Z).

我应该得到:Z = [2,2,2,2]。

containsN(4,W,[3,3,3,3])

我应该得到:W = 3。

换句话说,对于第一个例子,我需要在绑定到Z的列表中有4个2的实例。

对于第二个例子,我需要将列表中的元素应用4次绑定到W。

到目前为止,我的尝试导致无限循环:

containsN(Y,W,Z) :- contains_helper(Y,W,Z).

contains_helper(0,_,_).
contains_helper(Y,W,[H|T]) :- W = H, Y0 is Y - 1, contains_helper(Y0,W,T).

我的想法是,我称之为辅助函数,以便我可以逐个检查Z的元素。当计数器达到0时,我知道列表为真,因为每次迭代H = W.但是,我得到一个无限循环。

1 个答案:

答案 0 :(得分:2)

如果您希望谓词尽可能通用(我将其重命名为repeat/3

?- repeat(X, N, L).
N = 0, L = [] ;
N = 1, L = [X] ;
...

您可以使用length/2的漂亮属性,如下所示:

% True when L is a list with N repeats of X
repeat(X, N, L) :-
    length(L, N),
    maplist(=(X), L).

在这里,length(L, N)可以检查列表的长度,或者生成所需长度的列表,或者在回溯时生成增加长度的列表。

如果列表L的每个元素与变量X统一,maplist(=(X), L)将成功。您可以将其写为:

foo([], _).
foo([X|Xs], X) :-
    foo(Xs, X).

但我不认为这是必要的。