2

I'm trying to solve Knight Tour problem. I want to call a rule to evaluate possible movements, but I can't do that my rule returns the next position in the variable that I send.

    move(X,Y):-
      X is X+1,
      Y is Y-2.
    move(X,Y):-
      X is X+2,
      Y is Y-1.

In the console I send move(2,2) for example and I hope that returns 3,0 and 4,1 but returns false.

false
  • 10,264
  • 13
  • 101
  • 209
Joseph
  • 97
  • 3
  • 9

2 Answers2

3

In addition to the answer provided by @coder (+s(0)), I would suggest the use of library(clpfd), a pair representation for the coordinates and a name that reflects which argument is what, e.g. from_to/2. Then your predicate could look something like this:

:- use_module(library(clpfd)).

from_to(X-Y,X1-Y1):-
   X1 #= X+1,
   Y1 #= Y-2.
from_to(X-Y,X1-Y1):-
   X1 #= X+2,
   Y1 #= Y-1.

Using clpfd makes it possible to use the predicate both ways, e.g.: I'm at position 3-4, where can I move to?

   ?- from_to(3-4,T).
T = 4-2 ? ;
T = 5-3

Or: I'm at position 3-4, where could I have come from?

   ?- from_to(F,3-4).
F = 2-6 ? ;
F = 1-5

The latter case doesn't work if you define your predicate using is/2, since in that case the expression on the right side is expected to be instantiated:

   ?- X is 3+4.
X = 7
   ?- 7 is X+4.
     ERROR!!
     INSTANTIATION ERROR- in arithmetic: expected bound value
   ?- 7 is 3+X.
     ERROR!!
     INSTANTIATION ERROR- in arithmetic: expected bound value
tas
  • 8,100
  • 3
  • 14
  • 22
2

You need to use new variables and add new parameters like:

move(X, Y, New_X, New_Y):-
      New_X is X+1,
      New_Y is Y-2.

That's because when you call move(2,2) X and Y are instantiated to the value 2 and they can't change, so you could pass two new uninstantiated variables which will be returned instantiated.

For example now if you call: move(2,2,X,Y)
X,Y will be instantiated (when predicate returns/succeeds) and the predicate will return you the right values in X,Y .

coder
  • 12,832
  • 5
  • 39
  • 53