Reputation: 482
I've been trying to work this out for a good hour now, and am not having any luck.
If I have a list of lists like so
[[tom, dick, harry], [janice, jane, jess]]
And they have the relations
happy(tom).
happy(dick).
happy(harry).
happy(janice).
unhappy(jane).
unhappy(jess).
I want to query each list individually and find out if they are unhappy or happy. Currently I have written two functions to handle this, they are
%% Female happiness checker
hcf([]).
hcf([H|T]) :-
happy(H),
hcf(T).
%% Male happiness checker
hcm([]).
hcm([H|T]) :-
happy(H),
hcM(T).
So currently individually these do work. If I put in
hcm([Janice, jess, jane]).
false
It returns false, as two people are unhappy.
What I am having trouble with is writing a function which allows me to pass each list from the list of lists into respective functions for each male and female happiness.
So Far I have tried something along the lines of
%% I was trying to get a HEAD list and a TAIL list to pass them through but didn't have much luck
happnieschecker([[]])
happnieschecker([[H|T]]) :-
some code here
EDIT : I want the program to run like so
happinesschecker([tom, dick, harry], [janice, jane, jess]).
false - since jane and jess are unhappy
happinesschecker([tom, dick, harry], [janice]).
true - since everyone is happy
So my question is, how can I pass every second list into HCF for females and every other list into HCM for males?
Upvotes: 1
Views: 2787
Reputation: 74177
A prolog list ([a,b,c]
) is syntactic sugar for the data structure ./2
, with the empty list denoted by the atom []
.
[a]
is exactly identical to .(a,[])
[a,b]
is exactly identical to .(a,.(b,[]))
[a,b,c]
is exactly identical to .(a,.(b,.(c,[])))
Myself, I'd rather use the square bracket notation. You?
Prolog's list notation offers more syntactic sugar, using the |
operator to partition the list into a head and a tail.
[a|X]
is exactly identical to `.(a,X)[a,b|X]
is exactly identical to .(a,.(b,X))
[a,b,c|X]
is exactly identical to .(a,.(b,.(c,X)))
Given that, and assuming your list-of-lists contains alternating sublists of males and females:
[ [bob,ted] , [carol,alice] , [tom,dick,harry] , [jane,sally,simone] ]
something like this should work for you
everybody_happy( [] ) . % the empty list is all happy
everybody_happy( [Ms] ) :- % a list of length 1 contains a male sublist
findall( M , (member(M,Ms),happy(M)) , Ms ) % is everybody happy?
. %
everybody_happy( [Ms,Fs|Ps] ) :- % a list of length 2+ starts with a male and female sublist
findall( M , (member(M,Ms),happy(M)) , Ms ) , % are all the boys happy?
findall( F , (member(F,Fs),happy(F)) , Fs ) , % are all the girls happy?
everybody_happy(Ps) % is the remainder of the list happy?
. % easy!
I'm using findall/3
here. If you want to roll your own happiness checker, just replace findall/3
with your implementation:
everybody_happy( [] ) . % the empty list is all happy
everybody_happy( [Ms] ) :- % a list of length 1 contains a male sublist
is_happy(Ms) % is everybody happy?
. %
everybody_happy( [Ms,Fs|Ps] ) :- % a list of length 2+ starts with a male and female sublist
is_happy( Ms ) , % are all the boys happy?
is_happy( Fs ) , % are all the girls happy?
everybody_happy(Ps) % is the remainder of the list happy?
. % easy!
is_happy([]). % the empty list is happy
is_happy([P|Ps] ) :- % a non-empty list is happy IF...
happy(P) , % - its head is happy, and
is_happy(Ps) % - its tail is happy
. % easy!
Edited to note: if you want to discard the first item, try something like
everybody_happy( [_|Xs] ) :-
every_body_happy_1( Xs )
.
where everybody_happy_1/1
is the actual predicate.
Upvotes: 1
Reputation: 10102
happynesschecker(Ms, Fs) :-
allhappy(Ms), % more compactly: maplist(happy,Ms).
allhappy(Fs).
allhappy([]).
allhappy([P|Ps]) :-
happy(P),
allhappy(Ps).
Note that the very same predicate can be used for both the males and females list.
And for a list of list of persons:
extrahappy(Mss) :-
maplist(maplist(happy), Mss).
or more verbosely:
extrahappy([]).
extrahappy([Ps|Pss]) :-
allhappy(Ps),
extrahappy(Pss).
Upvotes: 2