8.6 A Little Language for Logic Puzzles

The strategy for solving logic puzzles has three steps: Establish the properties and their values; write facts and rules for constraints; write solve and main to check the constraints, output, and backtrack.

Given the properties, values, and headers of constraints, the code of solve and main is completely boilerplate. It turns out that a fairly simple table contains all the information from which solve and main can be mechanically generated.

The table has two parts. The first part contains one line for each property which names the property and enumerates the possible values:


prolog/boy.puzzle
boy   red green blue
girl  red green blue
 
%%


These lines can be expanded into the facts about the property values and into the first part of solve that creates the variables, binds their values, and makes sure that the values are distinct.

The first part of the table ends with a line containing %% .

The second part of the table contains one line for each constraint:


prolog/boy.puzzle
boy,girl  a(red, green).


This tests a value for the property boy and a value for the property girl from the same tuple using the fact a . Note that the property names are combined with a comma and no white space.

The fact is output as is and the constraint check is automatically added to solve . The other constraints are specified in the same fashion:


prolog/boy.puzzle
boy,girl  c(red, X) :- X \= red.
boy,girl  d(green, X) :- X \= green.
boy,girl  e(blue, X) :- X \= blue.


puzzle2pl is implemented in awk . It reads the table shown above and generates a file to be consulted by Prolog before solve or main are queried.

$ puzzle2pl boy.puzzle > tmp.pl
$ pl
   ?- ['tmp.pl'].
   ?- main.
red     green
green   blue
blue    red
no