[comp.lang.prolog] Jobs problem: another solution

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.'