Posts: 325
Threads: 18
Joined: Jul 2006
Has anyone written an RPN program for the Towers of Hanoi that's theoretically capable of handling the full 64-disk configuration? Or must I finish mine?
There's one for the 32S in the software library for up to six disks and V had a 16C program for up to thirty-some disks, but I haven't seen one that can theoretically handle 64.
It's all but trivial in RPL, but in RPN without local variables and without adequate inbuilt support for recursion... And, of course, I don't expect the batteries to last long enough, and I'm not going to check the full results...
Posts: 274
Threads: 23
Joined: Sep 2007
Hi,
Can you post the program for the 16C or an URL to the program.
Knowing the 16C, I don't see why it could not be able to handle 64 discs (theoricaly :) ).
The only problem I see is the lack of speed to achieve the full move. My only hope is to have an 12C+ re-purposing to a 16C on last hardware (just dreaming).
I suspect 30 disc is already out of reach for the 16C.
Patrice
Posts: 1,619
Threads: 147
Joined: May 2006
I'll write one, but what must a ToH program do? Just count from 1 to 2^d - 1. The source peg is (count & (count - 1)) % 3 and the target is ((count | (count -1)) + 1) % 3.
Edited: 2 Nov 2010, 6:39 p.m.
Posts: 274
Threads: 23
Joined: Sep 2007
Posts: 1,619
Threads: 147
Joined: May 2006
Quote:
I'll write one, but what must a ToH program do?
Ok, based on the 16C example above, a ToH program should walk you through solving ToH.
Below is my version that will work for up to 64 discs on the 16C based on the equations I posted above.
Just GSB 0, then a 2 digit number will be displayed. The first number is the source rod and the second digit is the target rod. Press R/S to get the next set of numbers. This will solve any number of discs up to 64. Just keep pressing R/S until your problem is solved. For the case of 64, when the counter reaches 0, 0 will be displayed indicating that the 64 disc solution is solved.
Example output for 3 discs (23-1 moves):
13
12
32
13
21
23
13
Code:
001 - 43,22, 0 LBL 0
002 - 42 3 SET COMPL UNSGN
003 - 24 DEC
004 - 6 6
005 - 4 4
006 - 42 44 WSIZE
007 - 0 0
008 - 44 0 STO 0
009 - 43,22, 1 LBL 1
010 - 45 0 RCL 0
011 - 1 1
012 - 40 +
013 - 43 40 x=0
014 - 22 2 RTN
015 - 44 0 STO 0
016 - 45 0 RCL 0
017 - 1 1
018 - 30 -
019 - 42 20 AND
020 - 3 3
021 - 42 9 RMD
022 - 1 1
023 - 40 +
024 - 1 1
025 - 0 0
026 - 20 x
027 - 45 0 RCL 0
028 - 45 0 RCL 0
029 - 1 1
030 - 30 -
031 - 42 40 OR
032 - 1 1
033 - 40 +
034 - 3 3
035 - 42 9 RMD
036 - 1 1
037 - 40 +
038 - 40 +
039 - 31 R/S
040 - 22 1 GTO 1
Edited: 2 Nov 2010, 11:46 p.m.
Posts: 1,619
Threads: 147
Joined: May 2006
I should have stated my admiration for the 16C. What an awesome machine!
Posts: 304
Threads: 32
Joined: Nov 2005
There is also one in the software library for the 42S with graphical display of the disk moves:
Towers of Hanoi
Enjoy,
Juergen
Posts: 325
Threads: 18
Joined: Jul 2006
The 42S program apparently only handles up to 7 disks.
I'm putting on the finishing touches on a pair of 35s programs that will handle up to 64 disks each, using different algorithms. I also have a 27-step program for the 16C.
I hadn't seen Egan's formulae before. They sure make the thing easy, don't they?
Posts: 304
Threads: 32
Joined: Nov 2005
The 7-disk limitation is only because of the limited 42S graphics capabilities. The algorithm itself - which is non-recursive - can handle more disks ...
Posts: 274
Threads: 23
Joined: Sep 2007
Posts: 274
Threads: 23
Joined: Sep 2007
Hi Egan,
Quote:
Just count from 1 to 2^d - 1. The source peg is (count & (count - 1)) % 3 and the target is ((count | (count -1)) + 1) % 3.
Where did you find this formula ?
Patrice
Posts: 727
Threads: 43
Joined: Jul 2005
I remember looking at the Towers of Hanoi puzzle many years ago, when I discovered a non-recursive algorithm which I implemented on the HP-19C. I don't remember the details, but I do remember that it started when I discovered a simple pattern in the moves for each solution:
1 disc: 1-3
2 discs: 1-2 1-3 2-3
3 discs: 1-3 1-2 3-2 1-3 2-1 2-3 1-3
4 discs: 1-2 1-3 2-3 1-2 3-1 3-2 1-2 1-3 2-3 2-1 3-1 2-3 1-2 1-3 2-3
It becomes clearer when you change the destination peg from 3 to 2 for even numbers of discs:
1 disc: 1-3
2 discs: 1-3 1-2 3-2
3 discs: 1-3 1-2 3-2 1-3 2-1 2-3 1-3
4 discs: 1-3 1-2 3-2 1-3 2-1 2-3 1-3 1-2 3-2 3-1 2-1 3-2 1-3 1-2 3-2
For odd numbers of discs, you're always moving between pegs 1 and 3, then between 1 and 2, and then between 2 and 3, and then the pattern repeats. For even numbers of discs, the cycle is 1/2, 1/3, 2/3.
I don't remember how I derived the *direction* of each move, though. Of course this is easy to do by keeping track of the discs, but I distinctly remember discovering that that was not necessary. My algorithm must have been similar to Egan's formula, but I don't remember how I solved that last part.
This is going to drive me nuts now. :-)
UPDATE:
This refreshed my memory. The key is to notice the pattern of *which disc* is moved. Numbering the discs starting with the smallest being 0, the pattern of disc moves is 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,... In other words, you alternate between moving the smallest disc and some other one; discounting the moves of the smallest disc, you alternate between moving the second-smallest disc and some other one, etc. This much is easy to verify by looking at the recursive algorithm.
So at move n (starting from 1), you always move the disc m, where m is the lowest nonzero bit in the binary representation of n (with bit b being the one that represents 2b).
Using the 1/3, 1/2, 2/3 pattern I mentioned at the beginning (for odd numbers of discs; for even numbers, use 1/2, 1/3, 2/3), this means that the smallest disc (and all even-numbered discs) must move like 1-3, 3-2, 2-1; the second smallest (and all odd-numbered discs) must move like 1-2, 2-3, 3-1, for odd numbers of discs; for even numbers of discs, just swap pegs 2 and 3.
So, at move n, you must move disc m = floor(log2(n xor (n - 1))). How many times has disc m been moved prior to move n? Answer: p = floor((n - 1) / 2m + 1 + 1/2).
If the sum of the total number of discs and m is odd, you must move from peg 3 - (p + 2) % 3 to peg 3 - p % 3, and if the sum of the total number of discs and m is even, you must move from peg p % 3 + 1 to peg (p + 1) % 3 + 1.
This is still a bit ugly; we know how to get from the move number, n, to the number of the disc to be moved, m, and how to get from m to the number of times that that disc has been moved previously, p, but we can simplify that by combining those two functions: m(n) = floor(log2(n xor (n - 1))) and p(m) = floor((n - 1) / 2m + 1 + 0.5), so p(m(n)) = floor((n - 1) / 21 + floor(log2(n xor (n - 1))) + 1/2) = floor((n - 1) / ((n xor (n - 1)) + 1) + 1/2), and there you have a function that tells how many times the disc you have to move at move n has been moved previously; combining that with the formula that gives you the source and destination pegs for each disc given how many times it has been moved previously, plus the formula that tells you which disc m to move at any given move n, you have your 100% non-recursive algorithm.
Proving the 1/2-1/3-2/3 pattern and simplifying this mess to Egan's elegant formula is left as an exercise to the reader. :-)
Edited: 6 Nov 2010, 9:22 a.m.
Posts: 1,619
Threads: 147
Joined: May 2006
Posts: 325
Threads: 18
Joined: Jul 2006
I believe there's a bug in this program, one that only shows when doing 64 disks. And no, I don't blame Egan for not running this case to its completion :-)
Halfway through, when it's finally time to move the biggest disk:
count = 8000000000000000h
count-1 = 7FFFFFFFFFFFFFFFh
count or (count-1) = FFFFFFFFFFFFFFFFh
then (count or (count-1)+1) overflows. (2^64)mod 3 is 1 but the 16C, having lost the top bit, produces 0.
A partial fix is to replace the 1, + in lines 32-33 with 2, -. This will make it work correctly for the 64-disk case but the underflow screws up the 1-disk case.
Posts: 1,619
Threads: 147
Joined: May 2006
Here's a quick fix. I'll try to think of something better this weekend.
Replace:
((count | (count -1)) + 1) % 3
with:
((count | (count -1)) % 3 + 1) % 3
Posts: 325
Threads: 18
Joined: Jul 2006
Since I started this thread, I suppose I have to contribute my code to it. Here are ten programs for the full 64-disk Towers of Hanoi puzzle including RPN programs for the 35s, 30b, 16C, and 15C. The 30b is by far the fastest of this lot.
Posts: 735
Threads: 34
Joined: May 2007
Very nice paper! Thanks a lot for sharing.
However I assume there's a typo in the recursive RPL program:
Quote:
n 1. = t d s \<-h EVAL
Should be:
n 1. - t d s \<-h EVAL
Kind regards
Thomas
Posts: 325
Threads: 18
Joined: Jul 2006
Thanks. I've corrected that and fixed some other transcription errors in the 30b version.
Posts: 1,253
Threads: 117
Joined: Nov 2005
Indeed a great contribution, thanks for sharing it.
I don't suppose you could also add another version for the 41, or could you? I remember your original contributions to the PPC journal on the same subject, so it's been a while since then and it's great to see how you've come full circle :)
Best,
'AM
Posts: 735
Threads: 34
Joined: May 2007
Unfortunately I have also trouble with iterative RPL program:
Quote:
UNROT OR #2d - DUP #3d / #3d x
Here I assume a minus is missing at the end.
I've also changed the #2d - to #1d + though I
know what you possibly had in mind. But I prefer
to have the first move displayed correctly in all cases than
having the last one in the special case of n=64.
In the condition of the do-loop I simply use:
UNTIL
DUP2 ==
END
Otherwise the program did not end.
There's a minor typo on page 7: 234 mod 2 = 1
Probably you mean: 234 mod 3 = 1.
At least that would make sense in this context.
Cheers
Thomas
Edited: 17 Nov 2010, 5:01 p.m.
Posts: 1,477
Threads: 71
Joined: Jan 2005
Excellent writeup and programming work! Why not post this in the articles section here to make it more accessible to everyone?
-Katie
Posts: 325
Threads: 18
Joined: Jul 2006
I'd like to, but it's going to take some time unless I can find a good way to convert a LaTeX document to HTML. Any suggestions?
Posts: 735
Threads: 34
Joined: May 2007
cf. Advanced Article Formatting
Quote:
If you don't have a place to host your images, then please log in and request a guest directory. Once the directory is created, you will be able to upload your files. (This is actually preferred since I won't have to worry about the images moving or disappearing in the future and leaving broken links.)
Create an article with a short abstract and provide
a link to the PDF. It's not possible to upload HTML anyway.
How did you create the nice listings in LaTeX?
Best regards
Thomas
Posts: 325
Threads: 18
Joined: Jul 2006
Quote:
I remember your original contributions to the PPC journal on the same subject, so it's been a while since then and it's great to see how you've come full circle :)
Thanks for making me feel old. And to make me even older, I can't remember writing for the PPCJ about the Towers of Hanoi. Eight Queens, yes. The Game of Life, yes. The Towers, no.
As for the 41 (and I presume, the 42), it's simple to translate the first (recursive) 35s program. Number the black triangles showing the destinations of branches. Type in the program and put in the labels where needed. Instead of variable I, use register R00 so that DSE I becomes DSE 00, RCL(I) becomes RCL IND 00, and so forth. Or use synthetics and use M or N. IP is INT and RMDR is MOD. I didn't include a 41 program because I don't have a working 41 and I didn't want to use an emulator (all of the programs were done on the actual hardware).
For a bare-bones 41 without additional memory, use the 15C program, using R33 for RAN#.
I still want to shoehorn the program into the 19C/29C. A 12C version would be fun, as well.
Posts: 325
Threads: 18
Joined: Jul 2006
Quote:
How did you create the nice listings in LaTeX?
Very carefully. Below is an excerpt from the 30b version.
\noindent\begin{tabular}{|rl|rl|rl|rl|}
\hline
\textsf{ 1}&\textsf{Input} &\textsf{ 29}&\textsf{2} &\textsf{ 57}&\textsf{EEX} &\textsf{ 85}&\textsf{RCL Data} \\
\textsf{ 2}&\textsf{0} &\textsf{ 30}&\textsf{Call04} &\textsf{ 58}&\textsf{2} &\textsf{ 86}&\textsf{EEX} \\
...
\textsf{ 26}&\textsf{*} &\textsf{ 54}&\textsf{Math} &\textsf{ 82}&\textsf{\underline{Lbl 03}} &\textsf{110}&\textsf{Up} \\
\textsf{ 27}&\textsf{RCL Data} &\textsf{ 55}&\textsf{Up} &\textsf{ 83}&\textsf{Call04} &\textsf{111}&\textsf{Input} \\
\textsf{ 28}&\textsf{EEX} &\textsf{ 56}&\textsf{Input} &\textsf{ 84}&\textsf{+} &\textsf{112}&\textsf{RTN} \\
\hline
&\multispan{6}\textsf{\hfil \ length/checksum = 142.056\hfil}&\\
\hline
\end{tabular}\label{prog.30b.r}
There are easier ways, and I have some scripts that handle numbering and columnating (is that a word?).
|