ram@altger.UUCP (Reimer A. Mellin) (12/07/88)
Hello, The uEMACS Macro-language is quite powerful but can't handle recursive function-calls (at least in 3.9i). So here is one way of implementing recursive calls.... As a first test I programmed the Towers of Hanoi. Please realize that my version isn't programmed for speed but for straightforwardness (mostly :-). You should have the programm 'banner' on your system, because hanoi will use it via 'pipe-command' to generate a neat title-page. The numbers of the disks are also restricted to 9, because the pushing of the parameters is done with characters. (someone going to fix this ?, maybe pushing of %number as '&chr %number' and reading with '&asc %number' ?) starting hanoi: interpret hanoi.cmd with the '-f'-option or with the 'execute-buffer'-command. Then call the procedure hanoi with 'run hanoi'. Hanoi then asks for the number of disks and will display the moves. At this point I want to express my thank to Daniel Lawrence for this really small, neat, powerful and FREE editor. Greetings Reimer Mellin ------------------------S-T-A-R-T---------------------------------------- #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: hanoi.cmd # Wrapped by ram@ramsys on Wed Dec 7 00:39:33 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'hanoi.cmd' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hanoi.cmd'\" else echo shar: Extracting \"'hanoi.cmd'\" \(4811 characters\) sed "s/^X//" >'hanoi.cmd' <<'END_OF_FILE' X; The Towers of Hanoi for the uEMACS 3.9e X; Author: Reimer A. Mellin (ram@altger) X; Date: 6.12.1988 X; Implements the recursive algorith. with a buffer :-) X; Well, why shouldn't it work ? X; Just intended as a test version for recursion .... X; Copy, modify, use, abuse this as you like .... X X; BTW: dont forget Green-peace and all organizations against famine in X; the third world. X X X;This procedure pushes the string %pusharg on our stack .... X;i.e. writes at the end of the buffer Xstore-procedure push X select-buffer [stack] X insert-string %pusharg X newline X!endm X X;here we kill our actual context (the previous line in the stack-buffer) X;and re-read our old context !!! Xstore-procedure pop X select-buffer [stack] X previous-line X kill-to-end-of-line X run readarg X!endm X X; read the current incarnation of our variables on the stack. Xstore-procedure readarg X select-buffer [stack] X set-mark X previous-line X exchange-point-and-mark X copy-region X set %number &left $kill 1 X set %src &mid $kill 2 1 X set %aux &mid $kill 3 1 X set %dest &mid $kill 4 1 X!endm X X;just a silly procedure to print our first screen of the towers Xstore-procedure init-screen X beginning-of-file X set-mark X end-of-file X kill-region X set %i 0 X !while ¬ &equ %i &sub 10 %number X insert-string &cat %trenner &cat %disk0 X insert-string &cat %trenner &cat %disk0 X insert-string &cat %trenner &cat %disk0 X newline X set %i &add %i 1 X !endwhile X set %j 1 X !while ¬ &equ %i 10 X set %ivar &cat "%disk" %j X insert-string &cat %trenner &cat &ind %ivar X insert-string &cat %trenner &cat %disk0 X insert-string &cat %trenner &cat %disk0 X newline X set %i &add %i 1 X set %j &add %j 1 X !endwhile X 75 insert-string "^" X update-screen X set %j @"Press Return to start the fun ..." X!endm X X; the various disks and their starting positions on the first screen Xstore-procedure init-vars X set %disk9 "#########|#########" X set %disk8 " ########|######## " X set %disk7 " #######|####### " X set %disk6 " ######|###### " X set %disk5 " #####|##### " X set %disk4 " ####|#### " X set %disk3 " ###|### " X set %disk2 " ##|## " X set %disk1 " #|# " X set %disk0 " | " X set %trenner " " X set %ynoL %number X set %ynoM 0 X set %ynoR 0 X set %xnoL 5 X set %xnoM 29 X set %xnoR 53 X!endm X X;do the move of the uppermost disk on 'src' to 'dest' Xstore-procedure moveone X select-buffer [output] X;delete old disk X beginning-of-file X set %yvar &cat "%yno" %src X set %xvar &ind &cat "%xno" %src X &sub 10 &ind %yvar next-line X set %old &mid $line %xvar 19 X %xvar forward-character X 19 delete-next-character X insert-string %disk0 X set &ind %yvar &sub &ind %yvar 1 X;insert on new place X beginning-of-file X set %yvar &cat "%yno" %dest X set &ind %yvar &add &ind %yvar 1 X set %xvar &ind &cat "%xno" %dest X &sub 10 &ind %yvar next-line X &sub %xvar 1 forward-character X 19 delete-next-character X insert-string %old X X beginning-of-file X update-screen X!endm X X;the trivial recursive hanoi algorithism. push news args before calling an X;new incarnation of 'move'. Xstore-procedure move X run readarg ; get new context !!!! X !if &equ %number 1 X run moveone X !return X !endif X set %pusharg &cat &sub %number 1 &cat %src &cat %dest &cat %aux X run push X run move X run pop X run moveone X set %pusharg &cat &sub %number 1 &cat %aux &cat %src &cat %dest X run push X run move X run pop X!endm X X X;straight forward coding of making the starting window and asking for X;the numbers of disks (with checking). Also handles initialisation and X;destruction of our internal buffers (for recursion and display). X;uses banner to get a neat display (at least on my machine). X; ???? Why can't i use 'unmark-buffer name' ???? Xstore-procedure hanoi X set %olddiscmd $discmd X set $discmd FALSE X delete-other-windows X set %savebuf $cbufname X select-buffer [output] X pipe-command "banner 'Towers of'" X set %savebuf1 $cbufname X set-mark X end-of-file X copy-region X next-window X yank X delete-other-windows X delete-buffer %savebuf1 X pipe-command "banner ' Hanoi!'" X set-mark X end-of-file X copy-region X next-window X yank X insert-string "for uEMACS 3.9e (and higher) by Reimer A. Mellin ....." X delete-other-windows X delete-buffer %savebuf1 X update-screen X*label1 X set %number @"How may disks on first pole (1-9) ?" X !if &or &sgr %number "9" &sle %number "1" X !goto label1 X !endif X run init-vars X run init-screen X; move %numbers disks from Left to Right using Middle X; don't change 'LMR' since the characters are used to construct some X; variables (using '&ind'). X set %pusharg &cat %number "LMR" X run push X run move X select-buffer [stack] X unmark-buffer X select-buffer [output] X set %number @"Finished .... Press Return ....." X unmark-buffer X select-buffer %savebuf X delete-buffer [stack] X delete-buffer [output] X set $discmd %olddiscmd X!endm END_OF_FILE if test 4811 -ne `wc -c <'hanoi.cmd'`; then echo shar: \"'hanoi.cmd'\" unpacked with wrong size! fi # end of 'hanoi.cmd' fi echo shar: End of shell archive. exit 0 -- Reimer A. Mellin UUCP : unido!altger!ram Germany->Bavaria->Munich VOICE: 49-89-791 36 68 "Real programmers don't write in any language, they patch ......"