Towers of Hanoi: Difference between revisions

Content added Content deleted
m (→‎simple text moves: added/changed whitespace and comments, changed the wording of the output.)
m (→‎pictorial moves: added/changed whitespace and comments, elided some dead code, broke apart a long line of assignments, changed the wording in the REXX section header.)
Line 2,561: Line 2,561:


===pictorial moves===
===pictorial moves===
This version pictorially shows the moves for solving the Town of Hanoi.
This REXX version pictorially shows the moves for solving the Town of Hanoi.


Quite a bit of code has been dedicated to showing a picture of the towers with the disks, and the movement of the disk (the move).   Coloring of the rings is attempted with dithering.
Quite a bit of code has been dedicated to showing a "picture" of the towers with the disks, and the movement of the disk (for each move).   "Coloring" of the disks is attempted with dithering.


In addition, it shows each move in a countdown manner (the last move is marked as #1).
In addition, it shows each move in a countdown manner (the last move is marked as #1).


No attempt is made to explain this version of the REXX program 'cause of the complexity and somewhat obtuse features of the REXX language, the smallest of which is support for ASCII and EBCDIC "graphic" characters (glyphs).   It may not be obvious from the pictorial display of the moves, but whenever a ring is moved from one tower to another, it is always the top ring that is moved   (to the target tower).
It may not be obvious from the pictorial display of the moves, but whenever a disk is moved from one tower to another, it is always the top disk that is moved   (to the target tower).
<lang rexx>/*REXX program shows pictorial moves to solve Tower of Hanoi (with N towers)*/
<lang rexx>/*REXX program shows pictorial moves to solve Tower of Hanoi (with N disks).*/
parse arg N .; if N=='' then N=3 /*Not given? Then use default 3 disks.*/
parse arg N .; if N=='' then N=3 /*Not given? Then use default 3 disks.*/
sw=80; wp=sw%3-1; blanks=left('',wp) /*define some default REXX variables. */
sw=80; wp=sw%3-1; blanks=left('',wp) /*define some default REXX variables. */
Line 2,576: Line 2,576:
#=0; z=2**N-1; moveK=z /*#moves; min# of moves; where to move.*/
#=0; z=2**N-1; moveK=z /*#moves; min# of moves; where to move.*/
@abc='abcdefghijklmnopqrstuvwxyN' /*dithering chars when many disks used.*/
@abc='abcdefghijklmnopqrstuvwxyN' /*dithering chars when many disks used.*/
ebcdic=('f0'x==0) /*determine if EBCDIC or ASCII machine.*/
ebcdic= ('f0'x==0) /*determine if EBCDIC or ASCII machine.*/


if ebcdic then do
if ebcdic then do; bar='bf'x; ar="df"x; boxen='db9f9caf'x; down="9a"x
bar='bf'x;ar='df'x;boxen='db9f9caf'x;tl='ac'x;tr='bf'x;bl='ab'x;br='bb'x;vert='fa'x;down='9a'x
tr='bc'x; bl="ab"x; br='bb'x; vert="fa"x; tl='ac'x
end
end
else do
else do; bar='c4'x; ar="10"x; boxen='b0b1b2db'x; down="18"x
bar='c4'x;ar='10'x;boxen='b0b1b2db'x;tl='da'x;tr='bf'x;bl='c0'x;br='d9'x;vert='b3'x;down='19'x
tr='bf'x; bl="c0"x; br='d9'x; vert="b3"x; tl='da'x
end
end


verts = vert || vert; Tcorners= tl || tr
verts= vert || vert; Tcorners= tl || tr
downs = down || down; Bcorners= bl || br
downs= down || down; Bcorners= bl || br
box = left(boxen,1); boxchars=boxen || @abc; bararrow= bar || bar || ar
box = left(boxen,1); boxChars= boxen || @abc
$.=0; $.1=N; k=N; kk=k+k
$.=0; $.1=N; k=N; kk=k+k


do j=1 for N; @.3.j=blanks; @.2.j=blanks
do j=1 for N; @.3.j=blanks; @.2.j=blanks; @.1.j=center(copies(box,kk),wp)
if N<=length(boxChars) then @.1.j=translate(@.1.j,,substr(boxChars,kk%2,1),box)
@.1.j=center(copies(box,kk),wp)
if N<=length(boxchars) then @.1.j=translate(@.1.j,,substr(boxchars,kk%2,1),box)
kk=kk-2
kk=kk-2
end /*j*/ /*populate the tower of Hanoi spindles.*/
end /*j*/


call showtowers; call mov 1,3,N
call showtowers; call mov 1,3,N; say
say 'The minimum number of moves to solve a ' N"-disk Tower of Hanoi is " z
say
say "The minimum number of moves to solve a " N ' Tower of Hanoi is ' z
exit
exit
/*─────────────────────────────MOV subroutine─────────────────────────────────*/
/*─────────────────────────────MOV subroutine─────────────────────────────────*/
mov: if arg(3)==1 then call rng arg(1) arg(2)
mov: if arg(3)==1 then call dsk arg(1) arg(2)
else do
else do; call mov arg(1), 6-arg(1)-arg(2), arg(3)-1
call mov arg(1), 6-arg(1)-arg(2), arg(3)-1
call mov arg(1), arg(2), 1
call mov arg(1), arg(2), 1
call mov 6-arg(1)-arg(2), arg(2), arg(3)-1
call mov 6-arg(1)-arg(2),arg(2), arg(3)-1
end
end
return
return
/*─────────────────────────────RNG subroutine─────────────────────────────────*/
/*─────────────────────────────DSK subroutine─────────────────────────────────*/
rng: parse arg from dest; #=#+1; pp=
dsk: parse arg from dest; #=#+1; pp=
if from==1 then do
if from==1 then do
pp=overlay(bl,pp,c.1)
pp=overlay(bl, pp, c.1)
pp=overlay(bar,pp,c.1+1,c.dest-c.1-1,bar)
pp=overlay(bar, pp, c.1+1, c.dest-c.1-1, bar) || tr
pp=pp || tr
end
end
if from==2 then do
if from==2 then do
lpost=min(2,dest)
lpost=min(2, dest)
hpost=max(2,dest)
hpost=max(2, dest)
if dest==1 then do
if dest==1 then do
pp=overlay(tl,pp,c.1)
pp=overlay(tl, pp, c.1)
pp=overlay(bar,pp,c.1+1,c.2-c.1-1,bar)
pp=overlay(bar, pp, c.1+1, c.2-c.1-1, bar)||br
pp=pp || br
end
end
if dest==3 then do
if dest==3 then do
pp=overlay(bl, pp,c.2)
pp=overlay(bl,pp,c.2)
pp=overlay(bar, pp,c.2+1, c.3-c.2-1, bar) ||tr
pp=overlay(bar,pp,c.2+1,c.3-c.2-1,bar)
end
pp=pp || tr
end
end
end
if from==3 then do
if from==3 then do
pp=overlay(br,pp,c.3)
pp=overlay(br, pp, c.3)
pp=overlay(bar,pp,c.dest+1,c.3-c.dest-1,bar)
pp=overlay(bar, pp, c.dest+1, c.3-c.dest-1, bar)
pp=overlay(tl,pp,c.dest)
pp=overlay(tl, pp, c.dest)
end
end
say translate(pp,downs,Bcorners || Tcorners || bar); say overlay(moveK,pp,1)
say translate(pp, downs, Bcorners || Tcorners || bar); say overlay(moveK,pp,1)
say translate(pp,verts,Tcorners || Bcorners || bar)
say translate(pp, verts, Tcorners || Bcorners || bar)
say translate(pp,downs,Tcorners || Bcorners || bar)
say translate(pp, downs, Tcorners || Bcorners || bar); moveK=moveK-1
$.from=$.from-1; $.dest=$.dest+1; _f=$.from+1; _t=$.dest
moveK=moveK-1
$.from=$.from-1; $.dest=$.dest+1; _f=$.from+1; _t=$.dest
@.dest._t=@.from._f; @.from._f=blanks; call showtowers
@.dest._t=@.from._f; @.from._f=blanks
call showtowers
return
return
/*─────────────────────────────SHOWTOWERS subroutine──────────────────────────*/
/*─────────────────────────────SHOWTOWERS subroutine──────────────────────────*/
showtowers: do j=N by -1 for N; _=@.1.j @.2.j @.3.j; if _\='' then say _
showtowers: do j=N by -1 for N; _=@.1.j @.2.j @.3.j; if _\='' then say _; end
end /*j*/
return</lang>
'''output''' &nbsp; when using the default input:
return</lang>
{{out}}when the default input was used:
<pre>
<pre>
░░
░░
Line 2,693: Line 2,684:
▓▓▓▓▓▓
▓▓▓▓▓▓


The minimum number of moves to solve a 3 Tower of Hanoi is 7
The minimum number of moves to solve a 3-disk Tower of Hanoi is 7
</pre>
</pre>