% file:    a10.pl
% author:  Robert Keller
% purpose: Sample solution to a10 Prolog problems

/*
 * Problem 3:
 *         Complete the definitions of Prolog predicates that respond to
 *         the following queries, made to the Prolog database in the following
 *         ensure_loaded directive. This database defines the following
 *         predicates:
 *
 * movie([Title, Year], Director, [... categories])
 *
 * actress(Name, [Birth City, Birth State], Birthyear)
 *
 * actor(Name, [Birth City, Birth State], Birthyear)
 *
 * plays(Player, Role, [Title, Year])
 *
 * Your predicate names must be exactly those given below, or your solutions
 * will not be able to pass the tests that will be applied in grading.
 *
 * Since the essence of the solutions is in your predicate definitions and
 * not the actual answers, we will provide the answers in test cases.
 *
 * In defining your predicates, remove the _ from the variables.  These
 * are present for now so the compiler doesn't complain about singleton
 * variables, which are often the sign of an error, such as a spelling error.
 *
 */

:- ensure_loaded('/cs/cs60/a/10/movies.pl').


/*
 * 1. directedBandits(Director) iff Director is the director of the movie 
 *    ['Bandits', 2001].
 */

directedBandits(Director) :- movie(['Bandits', 2001], Director, _).


/*
 * 2. directedByBay(Movie) iff Movie is directed by 'Michael Bay'.
 */

directedByBay(Movie) :- movie(Movie, 'Michael Bay', _).



/*
 * 3. actressAfter1970(Actress) iff Actress was born after 1970.
 */

actressAfter1970(Actress) :- actress(Actress, _, Date), Date > 1970.


/*
 * 4. player(Name, BirthPlace, Birthyear) iff either 
 *    actor(Name, BirthPlace, Birthyear) 
 * or actress(Name, BirthPlace, Birthyear).
 */

player(Name, Birthplace, Birthyear) :- actor(Name, Birthplace, Birthyear).
player(Name, Birthplace, Birthyear) :- actress(Name, Birthplace, Birthyear).


/*
 * 5. bornInLondon(Player) iff Player was born in ['London', 'England'].
 */

bornInLondon(Player) :- player(Player, ['London', 'England'], _).


/*
 * 6. playerAndDirector(Player) iff Player is a player that directed 
 *    some movie.
 */

playerAndDirector(Player) :- movie(_, Player, _), player(Player, _, _).


/*
 * 7. playedAndDirected(Player) iff Player is a player that directed a movie 
 *    in which he or she played.
 */

playedAndDirected(Player) :- movie(Movie, Player, _), plays(Player, _, Movie).


/*
 * 8. playedMultiple(Player) iff Player played in more than one movie.
 */

playedMultiple(Player) :- 
    plays(Player, _, Movie1), 
    plays(Player, _, Movie2),
    Movie1 \== Movie2.


/*
 * 9. playedInComedy(Player) iff Player played in a comedy.
 */

playedInComedy(Player) :- 
    plays(Player, _, Movie), 
    movie(Movie, _, Categories),
    member(comedy, Categories).


/*
 * 10. playedNotDirected(Director) iff Director directed some movies, but 
 *     played in at least one movie he/she did not direct.
 */

playedNotDirected(D) :- movie(_, D, _), plays(D, _, M), \+movie(M, D, _).


/*
 * member(X, L) is true iff X is a member of L.
 */

member(A, [A | _]).
member(A, [_ | X]) :- member(A, X).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Problem 4

solve(Conf) :-

%%%%%%%   [College,    Drink, Haircolor,    Sport,      State],  %%%%%%%%%

         [[    cmc,        _,         _,        _,          _], 
          [    hmc,        _,         _,        _,          _], 
          [ pomona,        _,         _,        _,          _],
          [scripps,        _,         _,        _,          _]] = Conf,

    perm([[      _, lemonade,        _,         _,          _], 
          [      _,     milk,        _,         _,          _], 
          [      _,      tea,        _,         _,          _],
          [      _,    water,        _,         _,          _]], Conf),

    perm([[      _,        _,    black,         _,          _], 
          [      _,        _,    blond,         _,          _], 
          [      _,        _,    brown,         _,          _],
          [      _,        _,      red,         _,          _]], Conf),

    perm([[      _,        _,       _,   football,          _],
          [      _,        _,       _,      rugby,          _],
          [      _,        _,       _,      track,          _],
          [      _,        _,       _,  waterpolo,          _]], Conf),

    perm([[      _,        _,       _,          _, california],
          [      _,        _,       _,          _,    indiana],
          [      _,        _,       _,          _,    newyork],
          [      _,        _,       _,          _, washington]], Conf),

   member([      _,        _,     black, football,          _],  Conf), % 1
   member([      _, lemonade,        _,         _,    indiana],  Conf), % 2
   member([      _,     milk,        _,         _, washington],  Conf), % 3
   member([    cmc,        _,        _,         _,    newyork],  Conf), % 4
   member([      _,      tea,        _,     rugby,          _],  Conf), % 5
   member([    hmc,        _,        _,     track,          _],  Conf), % 6
   member([ pomona,        _,    blond,         _,          _],  Conf), % 7

 ( member([scripps,        _,        _,         _, california],  Conf)  % 8
 ; member([scripps,        _,        _,         _,    indiana],  Conf) ),

   member([      _,    water,        _,         _,      State],  Conf), % 9
         westCoast(State),

\+ member([      _,        _,   brown,       track,         _],  Conf), % 10
\+ member([    hmc,        _,       _,          _, washington],  Conf), % 11
\+ member([scripps, lemonade,       _,          _,          _],  Conf), % 12
true.

westCoast(california).
westCoast(washington).

perm([], []).
perm(L, [A | M]) :-
    remove(A, L, R),
    perm(R, M).


remove(A, [A | L], L).
remove(A, [B | L], [B | M]) :- remove(A, L, M).


test :-
        setof(X, solve(X), Z),
        length(Z, L),
        nl,
        (L =:= 1 -> write('There is one solution:')
                 ; write('There are '), write(L), write(' solutions:')),
        nl, nl,
        showAll(Z),
        !.
test :- write('There is no solution.').


showAll([]).
showAll([A | X]) :- showOne(A), showAll(X).


showOne([]) :- nl.
showOne([A | X]) :- write(A), nl, showOne(X).


/* solution

[cmc,tea,brown,rugby,newyork]
[hmc,lemonade,red,track,indiana]
[pomona,milk,blond,waterpolo,washington]
[scripps,water,black,football,california]

*/