145312Sbostic# Towers of Hanoi in sed. 245312Sbostic# 3*62226Sbostic# @(#)hanoi.sed 8.1 (Berkeley) 06/06/93 445312Sbostic# 545312Sbostic# 645312Sbostic# Ex: 745312Sbostic# Run "sed -f hanoi.sed", and enter: 845312Sbostic# 945312Sbostic# :abcd: : :<CR><CR> 1045312Sbostic# 1145312Sbostic# note -- TWO carriage returns, a peculiarity of sed), this will output the 1245312Sbostic# sequence of states involved in moving 4 rings, the largest called "a" and 1345312Sbostic# the smallest called "d", from the first to the second of three towers, so 1445312Sbostic# that the rings on any tower at any time are in descending order of size. 1545312Sbostic# You can start with a different arrangement and a different number of rings, 1645312Sbostic# say :ce:b:ax: and it will give the shortest procedure for moving them all 1745312Sbostic# to the middle tower. The rules are: the names of the rings must all be 1845312Sbostic# lower-case letters, they must be input within 3 fields (representing the 1945312Sbostic# towers) and delimited by 4 colons, such that the letters within each field 2045312Sbostic# are in alphabetical order (i.e. rings are in descending order of size). 2145312Sbostic# 2245312Sbostic# For the benefit of anyone who wants to figure out the script, an "internal" 2345312Sbostic# line of the form 2445312Sbostic# b:0abx:1a2b3 :2 :3x2 2545312Sbostic# has the following meaning: the material after the three markers :1, :2, 2645312Sbostic# and :3 represents the three towers; in this case the current set-up is 2745312Sbostic# ":ab : :x :". The numbers after a, b and x in these fields indicate 2845312Sbostic# that the next time it gets a chance, it will move a to tower 2, move b 2945312Sbostic# to tower 3, and move x to tower 2. The string after :0 just keeps track 3045312Sbostic# of the alphabetical order of the names of the rings. The b at the 3145312Sbostic# beginning means that it is now dealing with ring b (either about to move 3245312Sbostic# it, or re-evaluating where it should next be moved to). 3345312Sbostic# 3445312Sbostic# Although this version is "limited" to 26 rings because of the size of the 3545312Sbostic# alphabet, one could write a script using the same idea in which the rings 3645312Sbostic# were represented by arbitrary [strings][within][brackets], and in place of 3745312Sbostic# the built-in line of the script giving the order of the letters of the 3845312Sbostic# alphabet, it would accept from the user a line giving the ordering to be 3945312Sbostic# assumed, e.g. [ucbvax][decvax][hplabs][foo][bar]. 4045312Sbostic# 4145312Sbostic# George Bergman 4245312Sbostic# Math, UC Berkeley 94720 USA 4345312Sbostic 4445312Sbostic# cleaning, diagnostics 4545312Sbostics/ *//g 4645312Sbostic/^$/d 4745312Sbostic/[^a-z:]/{a\ 4845312SbosticIllegal characters: use only a-z and ":". Try again. 4945312Sbosticd 5045312Sbostic} 5145312Sbostic/^:[a-z]*:[a-z]*:[a-z]*:$/!{a\ 5245312SbosticIncorrect format: use\ 5345312Sbostic\ : string1 : string2 : string3 :<CR><CR>\ 5445312SbosticTry again. 5545312Sbosticd 5645312Sbostic} 5745312Sbostic/\([a-z]\).*\1/{a\ 5845312SbosticRepeated letters not allowed. Try again. 5945312Sbosticd 6045312Sbostic} 6145312Sbostic# initial formatting 6245312Sbostich 6345312Sbostics/[a-z]/ /g 6445312SbosticG 6545312Sbostics/^:\( *\):\( *\):\( *\):\n:\([a-z]*\):\([a-z]*\):\([a-z]*\):$/:1\4\2\3:2\5\1\3:3\6\1\2:0/ 6645312Sbostics/[a-z]/&2/g 6745312Sbostics/^/abcdefghijklmnopqrstuvwxyz/ 6845312Sbostic:a 6945312Sbostics/^\(.\).*\1.*/&\1/ 7045312Sbostics/.// 7145312Sbostic/^[^:]/ba 7245312Sbostics/\([^0]*\)\(:0.*\)/\2\1:/ 7345312Sbostics/^[^0]*0\(.\)/\1&/ 7445312Sbostic:b 7545312Sbostic# outputting current state without markers 7645312Sbostich 7745312Sbostics/.*:1/:/ 7845312Sbostics/[123]//gp 7945312Sbosticg 8045312Sbostic:c 8145312Sbostic# establishing destinations 8245312Sbostic/^\(.\).*\1:1/td 8345312Sbostic/^\(.\).*:1[^:]*\11/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\31/ 8445312Sbostic/^\(.\).*:1[^:]*\12/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\33/ 8545312Sbostic/^\(.\).*:1[^:]*\13/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\32/ 8645312Sbostic/^\(.\).*:2[^:]*\11/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\33/ 8745312Sbostic/^\(.\).*:2[^:]*\12/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\32/ 8845312Sbostic/^\(.\).*:2[^:]*\13/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\31/ 8945312Sbostic/^\(.\).*:3[^:]*\11/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\32/ 9045312Sbostic/^\(.\).*:3[^:]*\12/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\31/ 9145312Sbostic/^\(.\).*:3[^:]*\13/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\33/ 9245312Sbosticbc 9345312Sbostic# iterate back to find smallest out-of-place ring 9445312Sbostic:d 9545312Sbostics/^\(.\)\(:0[^:]*\([^:]\)\1.*:\([123]\)[^:]*\1\)\4/\3\2\4/ 9645312Sbostictd 9745312Sbostic# move said ring (right, resp. left) 9845312Sbostics/^\(.\)\(.*\)\1\([23]\)\(.*:\3[^ ]*\) /\1\2 \4\1\3/ 9945312Sbostics/^\(.\)\(.*:\([12]\)[^ ]*\) \(.*\)\1\3/\1\2\1\3\4 / 10045312Sbostictb 10145312Sbostics/.*/Done! Try another, or end with ^D./p 10245312Sbosticd 103