1

I'm working on solving a logic puzzle using prolog for school. Here's the clues:

  1. Brown, Clark, Jones and Smith are 4 substantial citizens who serve their community as achitect, banker, doctor and lawyer, though not necessarily respectively.

    Brown, who is more conservative than Jones but more liberal than Smith, is a better golfer than the men who are younger than he is and has a larger income than the men who are older than Clark.

    The banker, who earns more than the architect, is neither the youngest nor the oldest.

    The doctor, who is a poorer golfer than the lawyer, is less conservative than the architect.

    As might be expected, the oldest man is the most conservative and has the largest income, and the youngest man is the best golfer.

    What is each man's profession?

    hint: to rank people for weath, ability, relative age, etc use the numbers 1,2,3,4 Be careful to state whether 1 represents, e.g., youngest or oldest. Doing this makes comparisons easy to code.

To code (as follows) interprets all the relationships, given by the clues, as a list of lists, wherein each list defines the

 %[profession,surname,politics,relative_age, relative_salary, golf_ability]:    

profession(L) :- L = [[_,'Brown',_,_,_,_],[_,'Jones',_,_,_,_],[_,'Clark',_,_,_,_],
    [_,'Smith',_,_,_,_]],
member([_,'Brown',P1,A6,M3,G3],L),
member([_,'Jones',P2,_,_,_],L),
member([_,'Clark',_,A3,_,_],L),
member([_,'Smith',P3,_,_,_],L),
    moreconservative(P1,P2),
    moreliberal(P1,P3),
    bettergolfer(G3,younger(_,A6)),
    richer(M3,older(_,A3)),
member(['banker',_,_,A1,M1,_],L),
member(['architect',_,P5,_,M2,_],L),
    richer(M1,M2),
    (A1 = 2;A1 = 3),
member(['doctor',_,P4,_,_,G1],L),
member(['lawyer',_,_,_,_,G2],L),
    worsegolfer(G1,G2),
    moreliberal(P4,P5),
member([_,_,4,4,4,_],L),
member([_,_,_,1,_,4],L).

I define the relative_politics,relative_salary,relative_age, and golf_ability relationships like so

EG:

    richer(4,1).
    moreconservative(4,1).
    poorer(1,4).
    poorer(1,3).

And it goes on for all relationships.

I think I have faithfully translated all of the clues to prolog but it just says fail when I query the database. EG:

   ?- profession(L).
    fail.

I am using NU Prolog. I'm wondering if I made an error in my translation of the clues or I omitted a fact that is needed for the database to satisfy all the conditions of the list L.

false
  • 10,264
  • 13
  • 101
  • 209
user1822789
  • 45
  • 2
  • 6

1 Answers1

1

bettergolfer(G3,younger(_,A6)) ... it doesn't work this way, in Prolog. Instead, have this

   (  member( X,L), age(X,AX), golf(X,GX),
      (  younger(AX,A6) -> better_golfer(G3,GX) ; true )),
   .....

age( [_,_,_,A,_,_],A).
golf([_,_,_,_,_,G],G).
.....

this means, all the persons (including none) that are younger than Brown, must be poorer golfers than he is.

There is a catch here, too. Since we're told about the men younger than Brown, it means there must exist at least one such man (unlike in the mathematical definition of implication). We have to code this too. For example,

    ( member(X,L), age(X,AX), younger(AX,A6) -> true ),
    .....

(using unique names for the new logvars of course). You'll have to make the same transformation for your richer(M3,older(_,A3)).

Great idea BTW, to have the comparison predicates defined in a generative fashion:

poorer(1,2). 
poorer(1,3). 
poorer(1,4). 
poorer(2,3). 
poorer(2,4). 
poorer(3,4).
richer(A,B):- poorer(B,A)

If you were to define them as arithmetic comparisons, poorer(A,B):- A<B., you could potentially run into problems with uninstantiated variables (as recently discussed here).

Community
  • 1
  • 1
Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • I made the adjustments that you suggested regarding the two clues where there are multiple options. Now I'm running into the problem of uninstantiated variables. I added (below): `(member(M,L), age(Y,AY), money(Y,GY), (older(AY,A3) -> richer(M3, GY); true)), (member(M,L), age(Y,AY), older(AY,A3) -> true),` for the second clue you mentioned. – user1822789 Nov 20 '13 at 17:52
  • I also added the predicate `money([_,_,_,_,M,_],M).` – user1822789 Nov 20 '13 at 17:57
  • @user1822789 a. you shouldn't use the same variable in different places - its first instantiation will interfere; you need to use new var name each time; b. in general, it's a *new* question. please 1. finish your dealings with this one (upvote/accept those of the answers that you deem good/helpful; we're supposed to accept an answer to signal that the question is closed; you asked about a problem with your code, and I shown you one :) ), and 2. do post a new question, and attach *all the code* as you have it now, and show how you run it and the error message that you get. :) – Will Ness Nov 20 '13 at 19:50
  • @user1822789 a. ... or define separate predicates; we can use any name as we like inside each predicate that we write. – Will Ness Nov 20 '13 at 19:53