Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to count how many times a character appears in a string list in Prolog?

Tags:

prolog

I want to check if a character exists in a string. So Atom is the string and Ch the character. name is a predicate that converts the string in a list of numbers according to the ASCII code.

find_element is a predicate that is supposed to be true only if element X is part of a list. C is a counter that tells us where exactly element X was found.

This is the result I am getting:

?- exists(prolog,g). [103][112,114,111,108,111,103] false.

-------> 103 is the ASCII code of letter "g" and the list [112,114,111,108,111,103] is the list that represents the string "prolog". The question exists(prolog,g) should have provided a true response.

However the find_element predicate is working correctly. I don't understand why this is happening because when I type for example

?- find_element(5,[3,4,5,6,5,2],X).

I am getting X= 3 ; X = 5 ; false. ---->

which is absolutely fine because it tells me that 5 is the 3rd and the 5th element of the list.

So the problem is that find_element is working when I type something like ?- find_element(5,[3,4,5,6,5,2],X) but it is not when I try to call the predicate exists (which calls find_element).

This is the code:

find_element(X,[X|T],1).

find_element(X,[H|T],C):- find_element(X,T,TEMPC), C is TEMPC +1.

exists(Atom,Ch):- name(Atom,[X|T]), name(Ch,Z), write(Z), write([X|T]), find_element(Z,[X|T],Count).

Thanks in advance

like image 320
Danai Tri Avatar asked Jan 21 '26 11:01

Danai Tri


1 Answers

I've cleaned a bit your code, and fixed a bug:

find_element(X,[X|_], 1).
find_element(X,[_|T], C) :-
    find_element(X,T,TEMPC),
    C is TEMPC +1.

exists(Atom, Ch):-
    name(Atom, L),
    name(Ch, [Z]),
    find_element(Z, L, _Count).

note name(Ch, [Z]) to extract the single character. Now

?- exists(pippo,o).
true

It's worth to note that

?- find_element(3, [1,2,3,4,1,2,3,4],P).
P = 3 ;
P = 7 ;
false.

?- nth1(P, [1,2,3,4,1,2,3,4], 3).
P = 3 ;
P = 7 ;
false.

your find_element/3 behaves as nth1/3, with arguments 1 and 3 swapped.

Of course there are simpler and more general ways to perform such test. Using ISO builtins like sub_atom/5 (a really powerful primitive for atom inspection)

?- sub_atom(pippo, _,_,_, o).
true ;

or memberchk/2, after the conversion to character lists that you already know (but using ISO builtin atom_codes/2)

exists(Atom, Ch):-
    atom_codes(Atom, L),
    atom_codes(Ch, [Z]),
    memberchk(Z, L).

To count occurrences of a sub_atom, library(aggregate) can be used

occurences(Atom, Ch, N) :-
  aggregate_all(count, sub_atom(Atom, _,_,_, Ch), N).

?- occurences(pippo, p, X).
X = 3.
like image 194
CapelliC Avatar answered Jan 25 '26 08:01

CapelliC



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!