15

I'm writing a program in prolog that count the number of occurrences of a number in a list

count([],X,0).
count([X|T],X,Y):- count(T,X,Z), Y is 1+Z.
count([_|T],X,Z):- count(T,X,Z).

and this is the output

?- count([2,23,3,45,23,44,-20],X,Y).
X = 2,
Y = 1 ;
X = 23,
Y = 2 ;
X = 23,
Y = 1 ;
X = 3,
Y = 1 ;
X = 45,
Y = 1 ;
X = 23,
Y = 1 ;
X = 44,
Y = 1 ;
X = -20,
Y = 1 ;
false.

it's count the same number several times

Any help is appreciated

Ratzo
  • 958
  • 1
  • 7
  • 13
  • 1
    See [`tcount/3`](http://stackoverflow.com/a/29960878/772868) for a logically pure definition. – false Jun 09 '15 at 08:35

3 Answers3

23

Instead of the dummy variable _ just use another variable X1 and ensure it does not unify with X.

count([],X,0).
count([X|T],X,Y):- count(T,X,Z), Y is 1+Z.
count([X1|T],X,Z):- X1\=X,count(T,X,Z).

However note that the second argument X is supposed to be instantiated. So e.g. count([2,23,3,45,23,44,-20],23,C) will unify C with 2. If you want the count for every element use

:- use_module(library(lists)).

count([],X,0).
count([X|T],X,Y):- count(T,X,Z), Y is 1+Z.
count([X1|T],X,Z):- X1\=X,count(T,X,Z).

countall(List,X,C) :-
    sort(List,List1),
    member(X,List1),
    count(List,X,C).

Then you get

 ?- countall([2,23,3,45,23,44,-20],X,Y).
   X = -20,
   Y = 1 ? ;
   X = 2,
   Y = 1 ? ;
   X = 3,
   Y = 1 ? ;
   X = 23,
   Y = 2 ? ;
   X = 44,
   Y = 1 ? ;
   X = 45,
   Y = 1 ? ;
   no
sumx
  • 587
  • 5
  • 6
  • At least for me, if I just replace `Y is 1+Z` with `succ(Z, Y)`, then I don't need the `countall/3` predicate at all to get all solutions upon backtracking. You should also try replacing `X1 \= X` with `dif(X1, X)`. –  Jan 13 '16 at 08:28
2

You can also use the include predicate:

count(L, E, N) :-
    include(=(E), L, L2), length(L2, N).
Björn Lindqvist
  • 19,221
  • 20
  • 87
  • 122
0
ocr(X,[],0):- !.
ocr(X,[Element|Rs],V):- X = Element -> ocr(X,Rs,Ocr), V is 1+ Ocr; ocr(X,Rs,V).

I did it like that. That gives you only one answer and finishes.

Andrei
  • 21