How do I write 'findall' in a Prolog code itself?

1.3k views Asked by At

So, I am very new to Prolog and I have to write a short code about timetable. How can I add the findall function to a code itself?

happening(monday,chemistry).
happening(monday,english).
happening(tuesday,chemistry).
happening(wednesday,maths).
happening(friday,chemistry).
happening(friday,maths).

And now I want to write a command that shows how many times do I have chemistry in a week.

find_lessons(X) :-
findall(X,happening(X,chemistry), Bag).
1

There are 1 answers

1
willeM_ Van Onsem On BEST ANSWER

I assume you want the result, so the Bag, so you should rewrite find_lessons(X) to find_lessons(Bag):

find_lessons(Bag) :-
    findall(X, happening(X,chemistry), Bag).

This will then give a list of days when there is a chemistry lesson, so:

?- find_lessons(Bag).
Bag = [monday, tuesday, friday].

to count the number of lessons, you can use length/2:

?- find_lessons(Bag), length(Bag, N).
Bag = [monday, tuesday, friday],
N = 3.

But one can do this more efficient. Right now there is overhead in constructing the list, and counting the elements. We can make use of the aggregate library [swi-doc] and use the aggregate/3 predicate [swi-doc]:

?- aggregate(count, X^happening(X, chemistry), Total).
Total = 3.

so we can count the number of chemistry lessons with:

:- use_module(library(aggregate))

num_chem_lessons(N) :-
    aggregate(count, X^happening(X, chemistry), N).