The Tower of Hanoi
Kevin
McMillin | Arizona State University | Tempe, Arizona
MAT 267: Calculus
III for Engineers | Spring 2008
Supervised by
Professor Naala Brewer
Maple 11 Version - Tower of Hanoi
| > | 2^64-1; |
| (1.1) |
| > | evalf[3]((2^64-1)/(365*24*60*60)); |
| (1.2) |
| > | MoveSequence
:= proc( n, A, B, C )
#if number of disks = 1, then print [A,C] if n=1 then [A,C] #else call the MoveSequence procedure recursively once to move the topmost N-1 pegs to the storage peg, #then move A to C, then call the MoveSequence procedure again to move the topmost N-1 pegs from the storage #peg to the destination peg else op([MoveSequence(n-1,A,C,B),[A,C],MoveSequence(n-1,B,A,C)]); fi end; |
| (2.1) |
| > | MoveSequence(3,A,B,C); |
| (2.2) |
| > | MoveSequence(1,A,B,C); |
| (2.3) |
| > | MoveSequence(2,A,B,C); |
| (2.4) |
| > | #get
plottools and plots packages
with(plottools): with(plots): #create the PegSetup using a sequence of rectangles, with heights and widths arbitrarily based to fit inside a small Cartesian coordinate system PegSetup:= seq(plottools[rectangle]( [i,0] , [i+.1,4] , color="Gold" ), i=1..3), plottools[rectangle]( [0,-.5] , [4,0] , color="DarkGrey" ): plots[display](PegSetup, axes=none, view=[0..4, -1..4], title = "Tower of Hanoi", titlefont=[Arial, Roman, 18]); |
![]() |
Letting Maple Store and Move the Disks
| > | n:=7:[seq(n+1-i,i=1..n)],[],[]; |
| (4.1) |
| > | L:=table([(A)=[seq(n+1-i,i=1..n)],(B)=[],C=[]]); |
| (4.2) |
| > | MoveOneDisk:=proc(P::table,M::list)
#we'll need some local variables to store temporary lists and tables local a, b, c, n, p; #create a temporary table p identical to table P by calling the entries for each index p:=table( [(A)=L[A] , (B)=L[B] , (C)=L[C]] ); #call the move generated above--[A,C] and store its values in two local variables a:=M[1]; b:=M[2]; #extract the number of operands (disks) in L[a]--7 in our example---and store it as n n:=nops( L[a] ); #set p[b] (an index of the table p) equal to the operand of P[b] at the nth value of P[a] p[b]:=[ op(L[b]) , L[a][n] ]; #set p[a] equal to P[a] at each value from 1 to n-1 (that is, remove the nth value of p[a]) p[a]:=L[a][1..n-1]; #finally, return the table p p; end; |
| (4.3) |
| > | MoveSequence(7,A,B,C); |
| (4.4) |
That's 127 moves! Let's try the first two draws in the sequence using our new procedure.
| > | L:=MoveOneDisk(L,[A,C]):
print(L); |
| (4.5) |
| > | L:=MoveOneDisk(L,[A,B]):
print(L); |
| (4.6) |
| > | MoveOneDiskDraw:=proc(T::table,q,r,n)
#the inputs q and r are arbitrary values representing the "height" and "width" of the pegs--that is, the space #on the Cartesian plane in which the pegs are drawn and separated. We will use 5 and 1, respectively, for our example. #we'll need four more local variables for this procedure: w to store the width #of the smallest drawn disk, h for the height (always 1/2) of each disk, #t for a table to store the peg reference numbers, and l for an traversal tool through the passed table parameter local h,w,t,l; #get packages for plots and plottools with(plots): with(plottools): #assign the width of the disk to be the 1/2 over the number of the disk #larger disks will therefore be the ones with the larger disk numbers and larger disk widths w:=1/(3*n); #the height will remain 1/4 h:=1/4; #use t to set up a local table for the pegs t:=table([(A)=1,(B)=2,(C)=3]); display(seq(seq(rectangle([t[l]-T[l][j]*w,j*h],[t[l]+T[l][j]*w+.1,(j-1)*h],color="Maroon"),j=1..nops(T[l])),l=[A,B,C]),axes=none); end: r:=MoveOneDiskDraw(L,5,1,6): display(r,PegSetup, title="Tower of Hanoi", titlefont=[Arial,Roman,18]); |
![]() |
| > | TowerOfHanoi:=proc(n::{1,2,3,4,5,6,7,8,9,10,11,12})
#in consideration for Maple's solving power, we'll limit the number of disks to 12. #use local procedures local MoveSequence, MoveOneDisk, MoveOneDiskDraw, DrawGeneration, i, L, Q, PEG_HEIGHT, PEG_WIDTH; PEG_HEIGHT = 5; PEG_WIDTH = 1; #import necessary packages with(plottools): with(plots): #copy above procedures, separated by comment lines #-------------------MoveSequence------------------- MoveSequence := proc( n, A, B, C ) if n=1 then [A,C] else op([MoveSequence(n-1,A,C,B),[A,C],MoveSequence(n-1,B,A,C)]); fi end; #-------------------MoveOneDisk-------------------- MoveOneDisk:=proc(P::table,M::list) local a, b, c, n, p; p:=table( [(A)=L[A] , (B)=L[B] , (C)=L[C]] ); a:=M[1]; b:=M[2]; n:=nops( L[a] ); p[b]:=[ op(L[b]) , L[a][n] ]; p[a]:=L[a][1..n-1]; p; end; #-----------------MoveOneDiskDraw------------------ MoveOneDiskDraw:=proc(T::table,PEG_HEIGHT,PEG_WIDTH,n) local h,w,t,l,PegSetup; PegSetup:=seq(rectangle( [i,0] , [i+.1,4] , color="Gold" ), i=1..3), plottools[rectangle]( [0,-.5] , [4,0] , color="DarkGrey" ): plots[display](PegSetup, axes=none, view=[0..4, -1..4]); w:=1/(3*n); h:=1/4; t:=table([(A)=1,(B)=2,(C)=3]); display(seq(seq(rectangle([t[l]-T[l][j]*w,j*h],[t[l]+T[l][j]*w+.1,(j-1)*h],color="Maroon"),j=1..nops(T[l])),l=[A,B,C]),axes=none,PegSetup); end: #----------------DrawGeneration-------------------- #This takes the sequence of draws and stores them as a list, DrawGeneration. DrawGeneration:=[MoveSequence(n,A,B,C)]; #create the initial table with all disks on peg A L:=table([(A)=[seq(n+1-k,k=1..n)],(B)=[],C=[]]); #create a new image plot for each move Q:=MoveOneDiskDraw(L,PEG_HEIGHT,PEG_WIDTH,n); for i from 1 to nops(DrawGeneration) do #this creates the move L:=MoveOneDisk(L,DrawGeneration[i]); #this step plots it Q:=Q,MoveOneDiskDraw(L,PEG_HEIGHT,PEG_WIDTH,n); od; display(Q, insequence=true, title="Tower of Hanoi", titlefont=[Arial,Roman,18]); end: |
Finally, we run the solution and watch the animation!
| > | TowerOfHanoi(7);
#the procedure takes inputs from 1 ≤ n ≤ 12 #to play the animation, click anywhere on the plot and use the submenu |
![]() |
| > |