I found a 3 year old question that helps me count the number of occurrences of variables within a list. The question had the answer below. The code works. But I can't understand how, can someone help me make sense of this?
Here is the answer with the code I found, writing in quotation marks is part of the answer:
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
I am very new to Prolog, I only understand one part of this code, and it is this
sort(List,List1),
member(X,List1),
I would appreciate an explanation of this the whole thing, especially how Y is being printed.
About counting, first try to think about the meaning of the code.
In this code,
succ(N0, N)
is (arguably) a better way to say "N
is the natural number afterN0
" thanN is N0 + 1
. One reason is thatsucc/2
was meant to be used in every direction:... while
is/2
should be used with unbound left operand. Take this query... for an example of
N
being a number instead of a free variable.Using the predicate:
One interesting property of
dif/2
, as opposed to\=/2
, is that it imposes a constraint on the variableX
in the last solution:X
cannot, from now on, take any of the values1
, or2
.For the reason why you get all answers using
dif/2
, consider:When you use
X \= Y
, Prolog tries to unify its arguments and fails if the unification succeeds. This means that you only get the solution in which all free variables have been unified to each other, but you miss solutions where free variables are different from each other.About the
Y = ...
, when you make a query at the top level, it reports to you all new variable bindings that were made during successful proofs of this query. As the most simple example:You don't need, of course, to print out the values of
X
by hand; just type a semicolon to get the next answer. After the last answer you get a full stop and return to the?-
prompt.About the sorting: it sorts the whole list, but only shows you the first 9 elements of the sorted list. See this FAQ page from SWI-Prolog. In a nutshell, the easiest is to type
; true
after your query, to make sure that there is at least one choice point, and usew
andp
to switch between showing the whole term and only some of it.Hope this helps.