CompilerSaysNo
CompilerSaysNo

Reputation: 415

Prolog seating constraints

I have to solve the following problem in Prolog. Alex, Fred and Jane are 3 children that have made a seesaw out of a plank that is 10 meters long. They mark 11 seating positions along the plank, each one meter apart. The number the seating positions as -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5 where 0 is the center position. Alex, Fred and Jane weight respective 4, 3, and 2 units of weight. They are interested to know how they can get the seesaw to balance when all three of them are seated somewhere along the plank, and each child has to sit on a different position.

One seating position is when Alex, Fred, and Jane are at positions -4, 2, and 5 since (-4 * 4) + (2 * 3) + (5 * 2) = -16 + 6 + 10 = 0. Another seating position for Alex, Fred and Jane is -4, 4 and 2, and yet another is -3, 2, and 3.

I have tried the following to solve this but get error: ERROR: Type error: integer' expected, found[_G11889,_G11892,_G11895]'

Can anyone please help explain where I have gone wrong/how to go about this?

Many thanks in advance

:-use_module(library(clpfd)).

find(Seats):-
    Seats=[Alex, Fred, Jane],
    Seats in -5..5,
    all_different(Seats),
    (Alex*4+Fred*3+Jane*2)#=0,     % I am not sure about this line
    labeling([],Seats).

Upvotes: 5

Views: 665

Answers (1)

user502187
user502187

Reputation:

I would use symmetry breaking to reduce the number of solutions. A simple symmetry is when (A,F,J) is a solution, so is also (-A,-F,-J). So we could possibly restrict to J #>= 0, and keep in mind if J #\= 0, then there is a flipped solution.

So we first begin by importing the CLP(FD) library:

Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.1.16)
Copyright (c) 1990-2014 University of Amsterdam, VU Amsterdam
?- use_module(library(clpfd)).

And then we formulate our query, instead of the (in)/2 one should use (ins)/2, as larsman has already noted. The use of (in)/2 causes also the error messsage. The parenthesis are not needed around the linear form. So we get:

?- Seats=[Alex, Fred, Jane],
   Seats ins -5..5,
   Jane #> 0,
   all_different(Seats),
   Alex*4+Fred*3+Jane*2 #= 0,
   label(Seats),
   write(Seats), nl, fail; true.
[-4,2,5]
[-4,4,2]
[-3,2,3]
[-2,0,4]
[-2,2,1]
[-1,-2,5]
[-1,0,2]
[0,-2,3]
[1,-4,4]
true.

You get unique solutions for different weights, and if you require that nobody is sitting in the middle of the seesaw. The weights 15, 10 and 6 do the job. Here is an example run, note the modified (ins)/2 statement:

?- Seats=[Alex, Fred, Jane],
   Seats ins -5.. -1\/1..5,
   Jane #> 0,
   all_different(Seats),
   Alex*15+Fred*10+Jane*6 #= 0,
   label(Seats),
   write(Seats), nl, fail; true.
[-4,3,5]
true.

Bye

Upvotes: 3

Related Questions