ken@aiai.ed.ac.uk (Ken Johnson) (10/04/89)
/*
* Here is my solution to this problem, which I first came across in
* Peter Ross's book `Advanced Prolog' (published in the UK by
* Addison Wesley, 1989). I am not claiming this to be a better
* version, just different.
*
* Copyright notice: This program handbuilt from lovingly hand-crafted
* predicates in my traditional oak-beamed Scottish workplace. You may
* make and distribute copies, recite the code out loud in public houses
* and in village streets, store it in a retrieval system etc., BUT if you
* sell copies at a profit, I want a share.
*
* To run the program type `test.' and it should just go by itself.
*/
test :-
has_job(Jra,Jrb,Jta,Jtb,Jsa,Jsb,Jpa,Jpb),
describe(roberta,Jra,Jrb),
describe(thelma,Jta,Jtb),
describe(steve,Jsa,Jsb),
describe(pete,Jpa,Jpb),
nl,
fail.
test :-
write('No [more] solutions'),
nl.
describe(Name,Job1,Job2) :-
write(Name),
write(' is the '),
write(Job1),
write(' and the '),
write(Job2),
write('.'),
nl.
% --------------------
% This is where the story really starts. Roberts has the jobs Jra Jrb,
% Thelma has Jta and Jtb, Steve has Jsa and Jsb and Pete has Jpa and
% Jpb.
% In the generate-and-test loop here I am applying all tests as early
% as possible. I think the operator @> may also be less than 100% well
% known: it means `collates alphabetically after'.
has_job(Jra,Jrb,Jta,Jtb,Jsa,Jsb,Jpa,Jpb) :-
% Roberta's jobs
right_sex_for(Jra,female),
right_sex_for(Jrb,female),
Jra @> Jrb,
% Roberta is not a boxer.
% Roberta, the chef and the police officer went golfing
% together. Therefore Roberta is not the chef and nor is
% she the police officer
different([Jra,Jrb,chef,police_officer,boxer]),
distinguish(Jra,Jrb),
% Thelma's jobs
right_sex_for(Jta,female),
right_sex_for(Jtb,female),
Jta @> Jtb,
distinguish(Jta,Jtb),
different([Jra,Jrb,Jta,Jtb]),
% Steve's jobs
right_sex_for(Jsa,male),
right_sex_for(Jsb,male),
Jsa @> Jsb,
distinguish(Jsa,Jsb),
different([Jra,Jrb,Jta,Jtb,Jsa,Jsb]),
% Pete's jobs
right_sex_for(Jpa,male),
right_sex_for(Jpb,male),
Jpa @> Jpb,
% Pete has no education beyond 9th grade. I suppose this
% means he can't be a teacher, nurse or policeman
different([Jpa,Jpb,teacher,nurse,police_officer]),
distinguish(Jpa,Jpb),
% All the jobs are different
different([Jra,Jrb,Jta,Jtb,Jsa,Jsb,Jpa,Jpb]).
right_sex_for(chef,female).
right_sex_for(guard,_).
right_sex_for(nurse,male).
right_sex_for(telephonist,male).
right_sex_for(police_officer,_).
right_sex_for(teacher,_).
right_sex_for(actor,male).
right_sex_for(boxer,_). % I think this has to be either sex, or
% you get no solutions
% The ad hoc hack
distinguish(chef,police_officer) :-
!,
fail.
distinguish(police_officer,chef) :-
!,
fail.
distinguish(_,_).
% Utility: Is everything in the list different? (Never called with empty
% list as argument so that case is not covered)
different([_]) :-
!.
different([H|T]) :-
member(H,T),
!,
fail.
different([_|T]) :-
different(T).
% ------------
member(X,[X|_]).
member(X,[_|T]) :-
member(X,T).
--
Ken Johnson, AI Applications Institute, 80 South Bridge, Edinburgh EH1 1HN
E-mail ken@aiai.ed.ac.uk, phone 031-225 4464 extension 212
`I have read your article, Mr Johnson, and I am no wiser now than when I
started'. -- `Possibly not, sir, but far better informed.'