2

Hello i have a problem with my implementation of the tower of hanoi. I need to print a list of list with the necessary moves, but my algorithm just work when the numbers of discs is N=1. This is my code

move(1,X,Y,_,L) :-  
    append([X],[Y],L).
move(N,X,Y,Z) :- 
    N>1, 
    M is N-1, 
    move(M,X,Z,Y),
    move(1,X,Y,_), 
    move(M,Z,Y,X).

And this is the result when N= 1.

?- move(1,left,right,_,L).

L = [left,right]

(16 ms) yes

i need something like this

    L = [[left,center],[left,right],[center,right],[left,center],[right,left],
      [right,center],[left,center],[left,right],[center,right],[center,left],
[right,left],[center,right],[left,center],[left,right],[center,right]]

When N=4

please if someone could help me i will be gratefull.

false
  • 10,264
  • 13
  • 101
  • 209
  • 1
    If this is your code exactly as you have shown here, notice that the first clause of `move` has 5 arguments, while the second clause has only 4 arguments. I am almost certain that this is a mistake. –  Oct 11 '16 at 08:47

2 Answers2

2

When describing lists in Prolog, always consider using notation!

For example, consider:

moves(1, X, Y, _) --> [X-Y].
moves(N, X, Y, Z) -->
    { N #> 1,
      M #= N-1 },
    moves(M, X, Z, Y),
    moves(1, X, Y, _),
    moves(M, Z, Y, X).

Note that this...

  • uses fewer arguments
  • avoids the use of append/3.

I have also taken the liberty to use...

  • the name moves//4 to make clear that we are describing moves, not a single move.
  • CLP(FD) constraints for declarative arithmetic (easier to understand)
  • (-)/2 for denoting pairs, as is the convention in Prolog.

Sample query, using the phrase/2 interface predicate for DCGs:

?- phrase(moves(4,left,right,center), Ls).
Ls = [left-center, left-right, center-right, left-center, right-left, ... ].
mat
  • 40,498
  • 3
  • 51
  • 78
  • Awesome answer ,note that the result was meant to be list of lists and not list but it is more clear this way.... – coder Oct 11 '16 at 22:00
  • 2
    Thank you for the encouragement! Yes, I have taken the liberty to use pairs instead. To use lists of lists, one only needs to change the first rule, replacing `X-Y` by `[X,Y]`, which is however the term `'.'(X, '.'(Y, []))` and thus somewhat wasteful in comparison to `-(X, Y)`. – mat Oct 11 '16 at 22:03
0

With some small changes you could write:

move(1,X,Y,_,[[X,Y]]).

move(N,X,Y,Z,L) :- 
    N>1, 
    M is N-1, 
    move(M,X,Z,Y,L1),
    move(1,X,Y,_,L2), 
    move(M,Z,Y,X,L3),
    append(L1,L2,L4),
    append(L4,L3,L).

Example:

?- move(4,left,right,center,L).
L = [[left, center], [left, right], [center, right], [left, center], [right, left], [right, center], [left, center], [left, right], [center, right], [center, left], [right, left], [center, right], [left, center], [left, right], [center, right]] ;
false.
coder
  • 12,832
  • 5
  • 39
  • 53