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

Jimmy Selgen Nielsen <jse-0I578M6uKxnkQYj/[email protected]>
Newsgroups gmane.comp.lang.perl.qotw.discuss
Message-ID <7858C99FF2E1C24BA3311BE8BEBE6A8E01D3A04F@limail.lint.lyngso-industri.dk>
Wow .. Easier than I first thought :)

Here's my first QOTW post and try.

Decided to use a hash for the tape contents since it greatly simplifies the
"infinite tape" problem :)
Also not the shortest entry, but I gains on readability (or so I like to
think).

Credits : the by_number sort was stolen from "learning perl"

/Jimmy
-------------------------------------------------------------------------
#!/usr/bin/perl -w

use strict;
our(@ARGV);

my $tape_pos = 0;
my $state = undef;
my %state_trans;
my %tape_contents;

sub read_state_file{
    my $fname = shift;
    open(FILE,"<$fname") or die "Unable to open $fname";
    while(<FILE>){
        if(/^\s*(\S+)\s+(\w+)\s+(\S+)\s+(\w+)\s+([r|l|R|L])\s*(\#.*)?$/){
            if(defined $state_trans{$1}{$2}){
                #already defined state/value
                die "state $1 value $2 already defined\n";
            }else{
                $state = $1 if(!defined $state);
                $state_trans{$1}{$2} = [$3,$4,$5];
            }
        }elsif(/^$/){
            #blank line, ignore
        }else{
            print STDERR "Illigal instruction : $_\n";
        }
    }
    close(FILE);
}

sub parse{
    my $n_tape_pos = 0;
    my $n_state = undef;
    STEP:for(;;){
        $tape_contents{$tape_pos} = '_' if !defined
$tape_contents{$tape_pos};
        last STEP if (!exists
$state_trans{$state}{$tape_contents{$tape_pos}});
        #save new tape_pos and state for after we modify tape_contents
        $n_tape_pos = $state_trans{$state}{$tape_contents{$tape_pos}}[2] eq
'L' ? -1 : 1;
        $n_state = $state_trans{$state}{$tape_contents{$tape_pos}}[0];
        #modify tape contents
        $tape_contents{$tape_pos}=
$state_trans{$state}{$tape_contents{$tape_pos}}[1];
        #set new state and tape position
        $state = $n_state;
        $tape_pos += $n_tape_pos;
    }
}

sub by_number {
  # a sort subroutine, expect $a and $b
  if ($a < $b) { -1 } elsif ($a > $b) { 1 } else { 0 }
}

sub main{
    die "nope .. not a file" if (!defined $ARGV[0]) or (! -f $ARGV[0]);
    read_state_file($ARGV[0]);
    $tape_contents{$tape_pos} = '_'; #initialize tape
    if(defined ($ARGV[1])){
        my $ctr = 0;
        foreach my $c (split('',$ARGV[1])){
            $tape_contents{$ctr++} = $c;
        }
    }
    parse();
    foreach my $c (sort by_number keys(%tape_contents)){
        print "$tape_contents{$c}";
    }
    print "\n";
}

main()
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.