#!/usr/bin/perl6

% hanoi.pl

% Towers of Hanoi puzzle solver in Prolog.

% Goal is to move, say, 4 disks from left peg

% to right peg, using the middle as a buffer.

% This version displays the state of the pegs after

each move

.

go :-

P1 = [1,2,3,4],

show(P1,[],[]),

solve(4, left, middle, right, P1,[],[],NP1,NP2,NP3).

% The main predicate is solve.

% N is the number of disks to move.

% They are to be moved from peg A to peg C, using B as a buffer.

% P1,P2,P3 give the state of the pegs before moving the disks.

% NNP1, NNP2, NNP3 give the new state after the disks have been moved.

solve(N,A,B,C,P1,P2,P3,P1,P2,P3) :- N == 0.

solve(N,A,B,C,P1,P2,P3,NNP1,NNP2,NNP3) :-

M is N - 1,

solve(M, A, C, B, P1, P2, P3,NP1,NP2,NP3),

% move(A, C),

update(A,C, NP1,NP2,NP3,NewP1,NewP2,NewP3),

solve(M, B, A, C, NewP1, NewP2, NewP3, NNP1,NNP2,NNP3).

update(A,B,P1,P2,P3,NewNewP1,NewNewP2,NewNewP3) :-

pop(A

,X

,P1

,P2

,P3

,NewP1

,NewP2

,NewP3

),
push(B

,X

,NewP1

,NewP2

,NewP3

,NewNewP1

,NewNewP2

,NewNewP3

),
show(NewNewP1, NewNewP2, NewNewP3).

% Note

, the following

pop and push operations work on any one

% of the three pegs. The Name argument tells what peg to manipulate.

pop(Name

,H

,P1

,P2

,P3

,NP1

,NP2

,NP3

) :-
Name == left, P1 = [H|T], NP1 = T, NP2 = P2, NP3 = P3.

pop(Name

,H

,P1

,P2

,P3

,NP1

,NP2

,NP3

) :-
Name == middle, P2 = [H|T], NP1 = P1, NP2 = T, NP3 = P3.

pop(Name

,H

,P1

,P2

,P3

,NP1

,NP2

,NP3

) :-
Name == right, P3 = [H|T], NP1 = P1, NP2 = P2, NP3 = T.

push(Name

,Elt

,P1

,P2

,P3

,NP1

,NP2

,NP3

) :-
Name == left, NP1 = [Elt|P1], NP2 = P2, NP3 = P3.

push(Name

,Elt

,P1

,P2

,P3

,NP1

,NP2

,NP3

) :-
Name == middle, NP1 = P1, NP2 = [Elt|P2], NP3 = P3.

push(Name

,Elt

,P1

,P2

,P3

,NP1

,NP2

,NP3

) :-
Name == right, NP1 = P1, NP2 = P2, NP3 = [Elt|P3].

show(P1,P2,P3) :-