#!/usr/bin/env ruby -wKU
# A simple implementation of a Turing machine.
classTuringMachine# Create a new TuringMachine. Giving a set of instructions as an Array of
# Strings (which will be parsed for you). Optionally, one may pass in the
# initial state of the tape as a String. The tape head will be positioned
# at the first character of the +tape+ string.
definitialize(instructions, tape='')@instructions=Parser.parse(instructions)# @tape_r contains the tape under the tape head and rightward.
# @tape_l contains the tape leftward from the tape head.
@tape_r= tape.split(//)@tape_l=[]end# The meat of it all. Loop through the instructions until none match the
# current state of the machine. At the end, print out the contents of the
# tape.
defrun
state =@instructions.first[:state]
keep_going =truewhile keep_going
keep_going =false@instructions.each do |instruction|if state == instruction[:state]and read == instruction[:read]
state = instruction[:set_state]
write(instruction[:write])
move(instruction[:move])
keep_going =trueendendend
output_tape
end# Read the value at the tape head. '_' represents blankness.
defread@tape_r.first ||'_'end# Write the value at the tape head.
defwrite(value)@tape_r[0]= value
end# Move the tape head right or left.
defmove(direction)case direction
when'R'@tape_l.unshift(@tape_r.shift)when'L'@tape_r.unshift(@tape_l.shift)endend# Writes the contents of the tape to STDOUT, stripping off any blanks on
# either end
defoutput_tape
output ="#{@tape_l.reverse}#{@tape_r}"
output.sub!(/^_+/,'')
output.sub!(/_+$/,'')STDOUT.puts(output)end# The Parser module just handles (surpise!) parsing the instructions.
moduleParser# Parse the instructions, ignoring blank lines and comments (lines
# starting with a #)
defself.parse(instructions)
instructions.map! do |instruction|case instruction
when/^\s*$/,/^\s*#/nilwhen/^(\w+)\s+(\w)\s+(\w+)\s+(\w)\s+(R|L)/{:state=>$1,:read=>$2,:set_state=>$3,:write=>$4,:move=>$5}elseraiseArgumentError,"Badly formed instruction '#{instruction}'"endend
instructions.compact
endendendif__FILE__==$PROGRAM_NAME
instructions =File.readlines(ARGV.first)
machine =TuringMachine.new(instructions,ARGV[1].to_s)
machine.run
end