Check if the list contains N instances of X (repeat XN times)
Given a query like:
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 out of 2 in the list associated with Z.
For the second example, I need an item in a list applied 4 times, associated with 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 that I call the helper function so that I can check the Z elements one by one. When the counter reaches 0, I know the list is true, because for each iteration, H = W. However, I get an infinite loop.
source to share
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 nice properties length/2
like:
% True when L is a list with N repeats of X
repeat(X, N, L) :-
length(L, N),
maplist(=(X), L).
This length(L, N)
can check the length of the list, or generate a list of the required length, or generate lists of increasing length on backtracking.
maplist(=(X), L)
will succeed if each element of the list L is concatenated with the variable X. You could write it like:
foo([], _).
foo([X|Xs], X) :-
foo(Xs, X).
but I don't think it is necessary.