问题
Given a query such as:
containsN(4,2,Z).
I should get: Z = [2,2,2,2].
or
containsN(4,W,[3,3,3,3])
I should get: W = 3.
So in other words, for the first example I need 4 instances of 2 in a list bound to Z.
For the second example I need the element in the list applied 4 times bound to W.
My attempt so far results in an infinite loop:
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).
The idea is, I call a helper function so that I can check the elements of Z one by one. When the counter reaches 0 I know the list is true because for each iteration H = W. However, I'm getting an infinite loop.
回答1:
If you want the predicate to be as general as possible (and I renamed it to repeat/3
)
?- repeat(X, N, L).
N = 0, L = [] ;
N = 1, L = [X] ;
...
You can use the nice properties of length/2
, like this:
% True when L is a list with N repeats of X
repeat(X, N, L) :-
length(L, N),
maplist(=(X), L).
Here, length(L, N)
can check for the list's length, or generate a list of the desired length, or generate lists of increasing length upon backtracking.
The maplist(=(X), L)
will succeed if each element of the list L unifies with the variable X. You could have written it as:
foo([], _).
foo([X|Xs], X) :-
foo(Xs, X).
but I don't think this is necessary.
来源:https://stackoverflow.com/questions/27310855/check-if-a-list-is-made-up-of-n-instances-of-x-repeat-x-n-times