[SPOILER] Perl Quiz of the Week #24 (Turing Machine simulation)

Bill Tucker <[email protected]>
Newsgroups gmane.comp.lang.perl.qotw.discuss
Message-ID <a0610050bbd6fa65d3b60@[192.168.1.100]>
I was a little surprised at how easy this was. I'd studied Turing 
machines in school, but had never actually implemented one.

I catch one thing I think is an input error that didn't (unless I 
missed it) get mentioned in the problem statement - more than one 
line in the program for a given state/tape symbol.

Thanks, that was fun.

Bill

---------------------------------------------------------------

#!/usr/bin/perl

use strict;

my (@tape, $tapePos, $state, %transitions, $filename, $new, $out, $move);

@tape = ();
$tapePos = 0;
%transitions = ();

sub parse_pgm
     {
     my $filename = shift;
     my ($fh);

     open ($fh,"<$filename") or die "Couldn't open $filename";

     while (<$fh>)
         {
         /^\s*(#.*)?$/ and next; # Skip blank and comment lines
         /^\s*(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+([LR])\s*(#.*)?$/i or 
die "Illegal line at line number $.: $_";
         (defined($state)) or $state = $1;  # This inits the state to 
the first one in the pgm
         (defined($transitions{$1}{$2})) and die "Stop confusing me! 
There are two program lines for state $1, tape value $2";
         $transitions{$1}{$2} = { 'STATE'=>$3, 'VALUE'=>$4, 'MOVE'=>$5 };
         }
     close ($fh);
     }

sub move
     {
     my $direction = shift;

     if (uc($direction) eq "L")
         {
         ($tapePos == 0) ? (unshift (@tape, '_')) : ($tapePos--);
         }
     else    # We made sure the direction was "L" or "R" when we parsed the pgm
         {
         (defined($tape[++$tapePos]))  or push (@tape, '_');
         }
     }

# Start of main

($filename = shift) or die "You didn't give me a program file!";
(@ARGV) ? (@tape = split('',shift)) : ($tape[$tapePos] = '_');

&parse_pgm($filename);

while (defined($transitions{$state}{$tape[$tapePos]}))
     {
     $new = $transitions{$state}{$tape[$tapePos]};
     $state          = $new->{STATE};
     $tape[$tapePos] = $new->{VALUE};
     &move($new->{MOVE});
     }

$out = join('',@tape);
$out =~ s/^\_*(.*?)\_*$/$1/;
print $out."\n";
exit;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.