I\'m kinda new to Prolog so I have a few problems with a certain task. The task is to write a tail recursive predicate count_elems(List,N,Count) condition
Preserve logical-purity with clpfd!
Here's how:
:- use_module(library(clpfd)).
count_elems([],_,0).
count_elems([X|Xs],Z,Count) :-
X #=< Z,
count_elems(Xs,Z,Count).
count_elems([X|Xs],Z,Count) :-
X #> Z,
Count #= Count0 + 1,
count_elems(Xs,Z,Count0).
Let's have a look at how versatile count_elems/3 is:
?- count_elems([1,2,3,4,5,4,3,2],2,Count). Count = 5 ; % leaves useless choicepoint behind false. ?- count_elems([1,2,3,4,5,4,3,2],X,3). X = 3 ; false. ?- count_elems([1,2,3,4,5,4,3,2],X,Count). Count = 0, X in 5..sup ; Count = 1, X = 4 ; Count = 3, X = Count ; Count = 5, X = 2 ; Count = 7, X = 1 ; Count = 8, X in inf..0 .
We could also use meta-predicate
tcount/3, in combination with a reified version of (#<)/2:
#<(X,Y,Truth) :- integer(X), integer(Y), !, ( X Truth=true ; Truth=false ).
#<(X,Y,true) :- X #< Y.
#<(X,Y,false) :- X #>= Y.
Let's run above queries again!
?- tcount(#<(2),[1,2,3,4,5,4,3,2],Count).
Count = 5. % succeeds deterministically
?- tcount(#<(X),[1,2,3,4,5,4,3,2],3).
X = 3 ;
false.
?- tcount(#<(X),[1,2,3,4,5,4,3,2],Count).
Count = 8, X in inf..0 ;
Count = 7, X = 1 ;
Count = 5, X = 2 ;
Count = 3, X = Count ;
Count = 1, X = 4 ;
Count = 0, X in 5..sup .
A note regarding efficiency:
count_elems([1,2,3,4,5,4,3,2],2,Count) left a useless choicepoint behind.tcount(#<(2),[1,2,3,4,5,4,3,2],Count) succeeded deterministically.