Prologue Assignment

This is a question for one of my assignments:

Write repCount(L, X, N) , which is true when N is the number of occurrences of X in the list L

Here is my code where I am trying to solve the problem recursively:

 repCount([], X, N) :- N is 0. repCount([H|T], X, N) :- count([H|T], X, N). count([], X, 0). count([H|T], X, N) :- count(T, X, N1), X =:= H, N is N1 + 1. 

And it works when I provide a list full of identical numbers, such as:

 ?- repCount([2,2,2], 2, N). N = 3. 

But if I put a list with at least one value:

 ?- repCount([2,2,22], 2, N). false. 

It returns false . I cannot understand why this is happening or how to change it in order to “skip” an inappropriate value, and not to declare all this false. Any input is appreciated.

+4
source share
6 answers
 count([H|T], X, N):- count(T, X, N1), X=:=H, N is N1 + 1. 

here you state that N must be N1 + 1 if X is H; however, you are not determining what should happen if X is not H (basically the else clause is missing) this should work:

 count([H|T], X, N):- count(T, X, N1), (X=:=H-> N is N1 + 1 ; N is N1). 

another way:

 count([H|T], X, N):- count(T, X, N1), X=:=H, N is N1 + 1. count([H|T], X, N):- X=\=H, count(T, X, N1), N is N1. 

but this is inefficient, since count (T, X, N1) will be called twice if X is not H. We can fix this by doing a check in the sentence header:

 count([H|T], H, N):- count(T, X, N1), N is N1 + 1. count([H|T], X, N):- count(T, X, N1), N is N1. 

or simply: count ([H | T], H, N): - the number (T, X, N1), N is equal to N1 + 1.

 count([H|T], X, N1):- X=\=H, count(T, X, N1). 
+4
source

Perhaps an interesting addition to what @magus wrote: If you only care about the number of elements and not the elements themselves, you can use findall / 3 as follows:

 list_elem_num(Ls, E, N) :- findall(., member(E, Ls), Ds), length(Ds, N). 
+2
source

Save - with a little help from tcount/3 and (=)/3 !

The goal of tcount(=(X),Es,N) is: "There are N elements in the list Es that are equal to X."

Request example:

  ? - tcount (= (X), [a, b, c, a, b, c, a, b, a], N).
 (N = 4, X = a
 ;  N = 3, X = b
 ;  N = 2, X = c
 ;  N = 0, dif (X, a), dif (X, b), dif (X, c)
 )  % terminates universally
+2
source

But if you are not allowed to "cheat", if you want to use recursion, you do not need to compare "==". You can use Prolog variable pooling to achieve the same goal:

 % Job done all instances repCount2([], _, 0). % Head unifies with X/2nd parameter - ie X found repCount2([H|T], H, N) :- repCount2(T, H, NewN), N is NewN + 1. % We got here, so X not found, recurse around repCount2([_|T], X, N) :- repCount2(T, X, N). 

In the second predicate, H is mentioned twice, which means that if the head of the list matches X, then the recursion is down, then add 1 to the result of the rest of the recursion (which ends with adding 0 - the basic case, which is a way to create a battery).

+1
source

Almost there ... you need to use a battery like this:

 repCount(Xs,Y,N) :- count(Xs,Y,0,N) % the 3rd argument is the accumulator for the count, which we seed as 0 . count([],_,N,N). % if the list is empty, unify the accumulator with the result count([X|Xs],Y,T,N) :- % if the list is non-empty, X == Y , % and the head of the list (X) is the the desired value (Y), T1 is T+1 , % then increment the count, and count(Xs,Y,T1,N) % recurse down, passing the incremented accumulator . % count([X|Xs],Y,T,N) :- % if the list is non-empty, X \== Y , % and the head of the list(X) is not the desired value (Y), count(Xs,Y,T,N) % simply recurse down . % 
0
source

The original question did not indicate whether there are restrictions on which predicates can be used.

If you are allowed to cheat, i.e. use higher order predicates such as "findall" that recurs for you. You yourself do the recursion, this can be done in one predicate:

 repCount(L, X, N) :- findall(X, member(X, L), ListOfX), length(ListOfX, N). 
0
source

Source: https://habr.com/ru/post/1397878/


All Articles