The Golfer Riddle (Prolog Solution)

You've seen a solution to the golfer riddle using forward-chaining. Now I'll show you a shorter version using Prolog (backward chaining).

/* The golfer-riddle, by Ernest Friedemann-Hill */
/* Prolog solution by Gernot Starke, July 2007 */

gcolor(blue).
gcolor(plaid).
gcolor(orange).
gcolor(red).

gpos(1).
gpos(2).
gpos(3).
gpos(4).

golfer( [_, C, P] ) :- gcolor(C), gpos(P).

golferRiddle( G1, G2, G3, G4) :-  golfer(G1),golfer(G2),golfer(G3), golfer( G4),
    G1 = [fred, FredCol, FredPos ], 
    G2 = [joe, JoeCol, 2],
    G3 = [tom, TomCol, TomPos], 
    TomPos =\= 1, TomPos =\= 4,
    TomCol \= orange,
    G4 = [bob, plaid, BobPos],

    /* unique colors */
    is_set([FredCol, JoeCol, TomCol, plaid]),

    /* unique positions */ 
    is_set([FredPos, TomPos, BobPos, 2]), 

    /* Fred's right neighbour wears blue */
    plus( FredPos, 1, FP1),
    member( [_, blue, FP1], [G1, G2, G3, G4]).

I based this solutions on a few simple ideas:

  • A golfer is a list consisting of exactly three elements, name, color, position.
  • I construct four such golfer-lists, G1-G4.
  • The names are given (G1.name == fred, G2.name == joe...)
  • I use variables wherever an information is missing. For example the second line in golferRiddle: G1=[fred, FredCol, FredPos]: Currently we do not know fred's position and color, therefore the two variables.

I tested this with SWIProlog, an excellent environment (although I still have difficulties in debugging Prolog programs - which is my own fault!)

The solution, as expected:

?- golferRiddle( G1, G2, G3, G4).

G1 = [fred, orange, 1],
G2 = [joe, blue, 2],
G3 = [tom, red, 3],
G4 = [bob, plaid, 4] ;

No.

Please note that I entered a semicolon after the G4-output to force Prolog to search for other solutions. It cannot find another one, therefore it replies with a bold "No".