[mercury-users] Constraint puzzles - understanding how to go from Prolog to Mercury

Daniel Patterson lists.mercury at dbp.mm.st
Tue Sep 6 10:34:43 AEST 2011

```Hi again,

An example used in The Art of Prolog (1986, page 216) is a puzzle that follows the similar pattern of "There are N people, each who have a different X, Y, and Z." followed by a series of clues that should completely describe a unique solution (because of the constraints about uniqueness). The prolog code they showed consisted of a series of logical statements that amounted to that clue, and then further logical statements to extract the desired information (the solution to the puzzle).

In trying to translate this to Mercury, I ran into problems due to the instantiatedness of some of the parts. I looked through the section of the reference manual on Solvers and the corresponding paper by Becket et al from 2006, but I couldn't tell if that was even talking about the type of problem I was trying to solve. I also looked through the Prolog -> Mercury guide, but didn't notice anything that pertained to these kind of problems.

Either way, the code I wrote (which was a simplified translation of what was written in The Art of Prolog), was the following. This problem involves the ranking of a programming competition between three individuals from different countries who prefer different sports. I've left out my attempts at writing the modes because none of them worked!

:- type nationality ---> american; australian; israeli.
:- type sport ---> tennis; basketball; cricket.
:- type name ---> michael; richard; simon.
:- type friend ---> friend(name, nationality, sport).

:- pred did_better(friend,friend,list(friend)).
did_better(A,B,[A,B,_]).
did_better(A,C,[A,_,C]).
did_better(B,C,[_,B,C]).

:- pred name(friend,name).
name(friend(A,_,_),A).
:- pred nationality(friend,nationality).
nationality(friend(_,B,_),B).
:- pred sport(friend,sport).
sport(friend(_,_,C),C).

main(!IO) :-
(
if
(
Friends = [friend(_,_,_),friend(_,_,_),friend(_,_,_)],
% clue 1
did_better(Man1Clue1,Man2Clue1,Friends),
nationality(Man2Clue1,american),
% clue 2
did_better(Man1Clue2,Man2Clue2,Friends),
name(Man1Clue2,simon),nationality(Man1Clue2,israeli),
sport(Man2Clue2,tennis),
% clue 3
first(Friends,ManClue3),sport(ManClue3,cricket),
% queries
list.member(Q1,Friends),name(Q1,Name),nationality(Q1,australian),
member(Q2,Friends),name(Q2,richard),sport(Q2,Sport)
)
then
% results
print(Name,!IO),
print(Sport,!IO)
else
print("Could not solve\n", !IO)
).

The main problems seemed to arise from the fact that all of the predicates were partially filling in the friends, so, for example, it would say that the final instantiatedness was friend(ground,free,free), for example.

Are these types of problems solvable, and if so, how? Or does someone have an example of the way that they have done it (it could be any similar problem, not just this one)?