Reputation: 467
So I have an assignment where I am to produce compatible meeting times between 3 different people. In the prolog file where I define predicates, there is a line given that has the name of the three people I am supposed to compare that reads as follows:
people([ann,bob,carla]).
Where we are supposed to match these names from a data file that defines facts, where a fact holds the following format:
free(ann,slot(time(7,0,am),time(9,0,am))).
My question is, how do I read through 'people' so that I can match names against each other?
My text book doesn't really explain prolog too well, and I am confused on what 'people' actually is (when I say what it actually is, I mean is 'people' a list? an array?) so I am having troubles even searching for a solution as to how to read through each name so I can compare them.
Upvotes: 1
Views: 549
Reputation: 3736
people([ann,bob,carla]).
is a fact. The predicate people/1
holds a list of people names. In prolog you have different ways to get elements from a list.
The most "dirtiest" version is just to write the list with a fixed number of elements:
?- people([P1,P2,P3]).
P1 = ann,
P2 = bob,
P3 = carla ;
false.
You should not do this, because it works only for sets of 3 people and you would have to alter your code everytime a person leaves/enters.
Normally you go through a prolog list where you just get the first element Head
and the rest of a list Tail
:
?- people([Head|Tail]).
Head = ann,
Tail = [bob, carla] ;
false.
By redoing this you can traverse through the whole list until the list has only one element left. To do this you need a help predicate, which I named person
. person
takes as first element a List and as second a variable (or a name for test). It unificates the variable with one element from the list:
person([H|_], H).
person([_|T], P):-
person(T, P).
?- people(L), person(L,P).
L = [ann, bob, carla],
P = ann ;
L = [ann, bob, carla],
P = bob ;
L = [ann, bob, carla],
P = carla ;
false.
It works as follows: you have a list and imagine you see the first element from it only. You have two choices here: first you are ok with just taking the head element as an output, so the second attribute should be the exact same as the head element: person([H|_], H).
Or second: you ignore the head element and try to find something in the rest of the list by just calling the predicate again with a smaller list: person([_|T], P):- person(T, P).
When a variable starts with an underscore _
you are not interested in its content.
Also worth knowing: there are (most likely) inbuild helper predicates such as member/2
which give you back any member of a list:
?- people(L), member(P,L).
will give you any person in L
.
To access a single timeslot for a choosen person you simply ask for the predicate free
with your person from the list:
?- people(L), member(P,L), free(P,S).
If you want to find a timeslot where all persons in the list have to participate you need to define a helper predicate. I named it hastime
hastime([],_).
hastime([H|L], S):-
free(H,S),
hastime(L,S).
The output of ?- people(L), free(_,S), hastime(L,S).
will give you a timeslot S
where everone has time. Before calling hastime/2
you guess a Timeslot S
. hastime/2
will look if all of the people have time on S
: if there are no people (empty list []
) you can accept any timeslot (_
). If there are at least one person H
in your list: ask if H
has time on timeslot S
and try if the other people from the list have this timeslot S
free as well by calling the predicate for the tail list.
If prolog choose a slot where not all of them have time, it will go back to the point where it choosed the timeslot S
and will look for a different value and try again. If there are no such timeslots it will return false.
Also hastime/2
can be used to find a timeslot by itself, but using it as a "generator" and test at the same time is a bit confusing.
Upvotes: 5