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 ( |
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). |
||
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 |
<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) |
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 |
||
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 |
||
tr='bf'x; bl="c0"x; br='d9'x; vert="b3"x; tl='da'x |
|||
end |
end |
||
verts |
verts= vert || vert; Tcorners= tl || tr |
||
downs |
downs= down || down; Bcorners= bl || br |
||
box |
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; |
do j=1 for N; @.3.j=blanks; @.2.j=blanks; @.1.j=center(copies(box,kk),wp) |
||
⚫ | |||
@.1.j=center(copies(box,kk),wp) |
|||
⚫ | |||
kk=kk-2 |
kk=kk-2 |
||
⚫ | |||
end /*j*/ |
|||
call showtowers; call mov 1,3,N |
call showtowers; call mov 1,3,N; say |
||
⚫ | |||
say |
|||
⚫ | |||
exit |
exit |
||
/*─────────────────────────────MOV subroutine─────────────────────────────────*/ |
/*─────────────────────────────MOV subroutine─────────────────────────────────*/ |
||
mov: if arg(3)==1 then call |
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), |
call mov arg(1), arg(2), 1 |
||
call mov arg(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 |
||
/* |
/*─────────────────────────────DSK subroutine─────────────────────────────────*/ |
||
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 |
||
end |
|||
if dest==3 then do |
|||
pp=overlay(bl, pp,c.2) |
|||
pp=overlay( |
pp=overlay(bar, pp,c.2+1, c.3-c.2-1, bar) ||tr |
||
end |
|||
⚫ | |||
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 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 |
|||
@.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: |
showtowers: do j=N by -1 for N; _=@.1.j @.2.j @.3.j; if _\='' then say _; end |
||
return</lang> |
|||
'''output''' 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> |
||