home *** CD-ROM | disk | FTP | other *** search
- ############################################################################
- #
- # File: turing.icn
- #
- # Subject: Program to simulate a Turing machine
- #
- # Author: Gregg M. Townsend
- #
- # Date: June 10, 1988
- #
- ###########################################################################
- #
- # This program simulates the operation of an n-state Turing machine,
- # tracing all actions. The machine starts in state 1 with an empty tape.
- #
- # A description of the Turing machine is read from the file given as a
- # command-line argument, or from standard input if none is specified.
- # Comment lines beginning with '#' are allowed, as are empty lines.
- #
- # The program states must be numbered from 1 and must appear in order.
- # Each appears on a single line in this form:
- #
- # sss. wdnnn wdnnn
- #
- # sss is the state number in decimal. The wdnnn fields specify the
- # action to be taken on reading a 0 or 1 respectively:
- #
- # w is the digit to write (0 or 1)
- # d is the direction to move (L/l/R/r, or H/h to halt)
- # nnn is the next state number (0 if halting)
- #
- # Sample input file:
- #
- # 1. 1r2 1l3
- # 2. 1l1 1r2
- # 3. 1l2 1h0
- #
- # One line is written for each cycle giving the cycle number, current
- # state, and an image of that portion of the tape that has been visited
- # so far. The current position is indicated by reverse video (using
- # ANSI terminal escape sequences).
- #
- # Input errors are reported to standard error output and inhibit
- # execution.
- #
- # Bugs:
- #
- # Transitions to nonexistent states are not detected.
- # Reverse video should be parameterizable or at least optional.
- # There is no way to limit the number of cycles.
- # Infinite loops are not detected. (Left as an exercise... :-)
- #
- # Reference:
- #
- # Scientific American, August 1984, pp. 19-23. A. K. Dewdney's
- # discussion of "busy beaver" turing machines in his "Computer
- # Recreations" column motivated this program. The sample above
- # is the three-state busy beaver.
- #
- ############################################################################
- #
- # Links: options
- #
- ############################################################################
-
- link options
-
- record action (wrt, mov, nxs)
-
- global machine, lns, lno, errs
- global cycle, tape, posn, state, video
-
- procedure main(args)
- local opts
-
- opts := options(args,"v")
- video := \opts["v"]
-
- rdmach(&input) # read machine description
- if errs > 0 then stop("[execution suppressed]")
- lns := **machine # initialize turing machine
- tape := "0"
- posn := 1
- cycle := 0
- state := 1
- while state > 0 do { # execute
- dumptape()
- transit(machine[state][tape[posn]+1])
- cycle +:= 1
- }
- dumptape()
- end
-
- # dumptape - display current tape contents on screen
-
- procedure dumptape()
- if cycle < 10 then writes(" ")
- writes(cycle,". [",right(state,lns),"] ",tape[1:posn])
- if \video then write("\e[7m",tape[posn],"\e[m",tape[posn + 1:0])
- else {
- write(tape[posn:0])
- write(repl(" ",6 + *state + posn),"^")
- }
- end
-
-
- # transit (act) - transit to the next state performing the given action
-
- procedure transit(act)
- tape[posn] := act.wrt
- if act.mov == "R" then {
- posn +:= 1
- if posn > *tape then tape ||:= "0"
- }
- else if act.mov == "L" then {
- if posn = 1 then tape := "0" || tape
- else posn -:= 1
- }
- state := act.nxs
- return
- end
-
- # rdmach (f) - read machine description from the given file
-
- procedure rdmach(f)
- local nstates, line, a0, a1,n
-
- machine := list()
- nstates := 0
- lno := 0
- errs := 0
- while line := trim(read(f),' \t') do {
- lno +:= 1
- if *line > 0 & line[1] ~== "#"
- then line ? {
- tab(many(' \t'))
- n := tab(many(&digits)) | 0
- if n ~= nstates + 1 then warn("sequence error")
- nstates := n
- tab(many('. \t'))
- a0 := tab(many('01LRHlrh23456789')) | ""
- tab(many(' \t'))
- a1 := tab(many('01LRHlrh23456789')) | ""
- pos(0) | (warn("syntax error") & next)
- put(machine,[mkact(a0),mkact(a1)])
- }
- }
- lno := "<EOF>"
- if *machine = errs = 0 then warn("no machine!")
- return
- end
-
- # mkact (a) - construct the action record specified by the given string
-
- procedure mkact(a)
- local w, m, n
-
- w := a[1] | "9"
- m := map(a[2],&lcase,&ucase) | "X"
- (any('01',w) & any('LRH',m)) | warn("syntax error")
- n := integer(a[3:0]) | (warn("bad nextstate"), 0)
- return action (w, m, n)
- end
-
- # warn (msg) - report an error in the machine description
-
- procedure warn(msg)
- write(&errout, "line ", lno, ": ", msg)
- errs +:= 1
- return
- end
-