% Solution to the extra credit logic puzzle.

% Facts (sister, months, day, weekday, weekend)
sister(abigail).
sister(brenda).
sister(mary).
sister(paula).
sister(tara).

% months in list so that index tells which comes earlier
months([february, march, june, july, december]).

% days in list so that index tells which comes earlier
days([sunday, monday, wednesday, friday, saturday]).

weekday(monday).
weekday(wednesday).
weekday(friday).
% weekend means not weekday so no need to make a new fact for that

solve :-
    months(Months),
    member(AMonth, Months), member(BMonth, Months), member(MMonth, Months), member(PMonth, Months), member(TMonth, Months),
    all_different([AMonth, BMonth, MMonth, PMonth, TMonth]),
    
    days(Days),
    member(ADay, Days), member(BDay, Days), member(MDay, Days), member(PDay, Days), member(TDay, Days),
    all_different([ADay, BDay, MDay, PDay, TDay]),
    
    Birthdays = [ birthday(abigail, AMonth, ADay),
              birthday(brenda, BMonth, BDay),
              birthday(mary, MMonth, MDay),
              birthday(paula, PMonth, PDay),
	          birthday(tara, TMonth, TDay) ],
              
              
    % 1a. Paula was born in March but not on Saturday.
    member(birthday(paula, march, _), Birthdays), 
    \+member(birthday(paula, _, saturday), Birthdays),

    % 1b. Abigail's birthday was not on Friday or Wednesday.
    \+member(birthday(abigail, _, friday), Birthdays),
    \+member(birthday(abigail, _, wednesday), Birthdays),
    
    % 2. The girl born on Monday was born earlier in the year than Brenda and Mary.
    not(Earlier == BMonth), not(Earlier == MMonth),
    earlier(Months, Days, Earlier, monday, BMonth, BDay), earlier(Months, Days, Earlier, monday, MMonth, MDay),
    member(birthday(_, Earlier, monday), Birthdays),

    % 3. Tara was not born in February. Her birthday was on weekend.
    \+member(birthday(tara, february, _), Birthdays), not(weekday(TDay)),
    
    % 4a. Mary was not born in December nor was her birthday on a weekday.
    \+member(birthday(mary, december, _), Birthdays), not(weekday(MDay)),

    % 4b. The girl whose birthday was in June was born on Sunday.
    member(birthday(_, june, sunday), Birthdays),

    % 5a. Tara was born before Brenda whose birthday was not on Friday.
    \+member(birthday(brenda, _, friday), Birthdays), earlier(Months, Days, TMonth, TDay, BMonth, BDay),
    
    % 5b. Mary was not born in July.
    \+member(birthday(mary, july, _), Birthdays),
    
    tell(abigail, AMonth, ADay),
    tell(brenda, BMonth, BDay),
    tell(mary, MMonth, MDay),
    tell(paula, PMonth, PDay),
    tell(tara, TMonth, TDay).
    
% Compare month first then day
earlier(_, Days, Month1, Day1, Month1, Day2) :- nth0(Index1, Days, Day1), nth0(Index2, Days, Day2), Index1 < Index2.
earlier(Months, _, Month1, _, Month2, _) :- nth0(Index1, Months, Month1), nth0(Index2, Months, Month2), Index1 < Index2.

tell(Sister, Month, Day) :- write(Sister), write(' was born on a '), write(Day), write(' in '), write(Month), 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([_]).