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.

+1


source to share


1 answer


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.

+2


source







All Articles