%the solution to the birthday problem

%facts
month(february).
month(march).
month(june).
month(july).
month(december).

girl(abigail).
girl(brenda).
girl(mary).
girl(paula).
girl(tara).

day(sunday).
day(monday).
day(wednesday).
day(friday).
day(saturday).

%solution
solve :-
    month(AbigailMonth), month(BrendaMonth), month(MaryMonth), month(PaulaMonth),
    month(TaraMonth),
    all_different( [AbigailMonth, BrendaMonth, MaryMonth, PaulaMonth, TaraMonth]),

    day(AbigailDay), day(BrendaDay), day(MaryDay), day(PaulaDay), day(TaraDay),
    all_different( [AbigailDay, BrendaDay, MaryDay, PaulaDay, TaraDay]),

    Birthdays = [ birthday(abigail, AbigailMonth, AbigailDay),
                  birthday(brenda, BrendaMonth, BrendaDay),
                  birthday(mary, MaryMonth, MaryDay),
                  birthday(paula, PaulaMonth, PaulaDay),
                  birthday(tara, TaraMonth, TaraDay) ],

%rules
%Paula was born in march but not on saturday. Abigails birthday was not on friday
%or wednesday
member(birthday(paula, march, _), Birthdays),
\+member(birthday(paula, _, saturday), Birthdays),

((\+member(birthday(abigail, _, friday), Birthdays),
    \+member(birthday(abigail, _, wednesday), Birthdays) ) ),

%the girl whose birthday is on monday was born earlier in the year than brenda and mary
\+member(birthday(brenda, _, monday), Birthdays),
\+member(birthday(mary, _, monday), Birthdays),

%tara wasnt born in february and her birthday was on the weekend
\+member(birthday(tara, february, _), Birthdays),
((member(birthday(tara, _, sunday), Birthdays) );
(member(birthday(tara, _, saturday), Birthdays) ) ),

%mary was not born in december nor was her birthday on a weekday.
%the girl whose birthday was in june was born on sunday
\+member(birthday(mary, december, _), Birthdays),
((member(birthday(mary, _, sunday), Birthdays);
    member(birthday(mary, _, saturday), Birthdays) ) ),
%member(birthday(_, june, sunday), Birthdays),

% tara was born before brenda, whose birthday wasnt on friday. mary wasnt
% born in july.
\+member(birthday(brenda, _, friday), Birthdays),
\+member(birthday(tara, december, _), Birthdays),
\+member(birthday(mary, july, _), Birthdays),


%display results
tell(abigail, AbigailMonth, AbigailDay),
tell(brenda, BrendaMonth, BrendaDay),
tell(mary, MaryMonth, MaryDay),
tell(paula, PaulaMonth, PaulaDay),
tell(tara, TaraMonth, TaraDay).

tell(Who, Month, Day) :- write(Who), write('s birthday is in '), write(Month),
write(' on '), write(Day), write('.'), nl.

% If the head of the list is in the tail, fail.
all_different([Head|Tail]) :- member(Head, Tail), !, fail.
% Otherwise, check the tail of the list.
all_different([_|Tail]) :- all_different(Tail).
% If there's only one thing in the list, it's fine.
all_different([_]).
