#!/usr/bin/perl
#!/bin/perl
$StudentName{'referencea'} = 'Kofi Laing Reference';
$StudentEmail{'referencea'} = 'laing@cs.tufts.edu';
$StudentName{'referenceb'} = 'Kofi Laing Reference';
$StudentEmail{'referenceb'} = 'aklaing@gmail.com';
$StepBound = 120000;
sub makestate {
local($State, $Label, $InitialOrNot, $FinalOrNot) = @_;
if ($InitialOrNot) {
$InitStateIndex = $State;
# print "Setting Initial State to $InitStateIndex\n";
}
if ($FinalOrNot) {
push(@FinalStateList, $State);
# print "Setting Final States to include $State\n";
}
}
sub transition {
local($State, $Next, $Read, $Write, $Move) = @_;
if (! $Seen{$State}{$Read}) {
$Seen{$State}{$Read} = 1;
$Transition{$State}{$Read} = [$Next,$Write,$Move];
if ($Debug) {
print "Setting from=$State read=$Read next=$Next write=$Write move=$Move\n";
}
} else {
&kmyerror(10, "Nondeterminism found and ignored.\n");
}
}
sub kmyerror { local($Number, $String) = @_;
print "ERROR[$Login, $FileName, $Number]: ", $String, "\n";
}
sub readxmlfile {
local($FileName) = @_;
$InitStateIndex = '';
@FinalStateList = ();
%Seen = ();
%Transition = ();
open(FILE, "< $FileName") ||
&kmyerror(100, "Could not open the file");
$XML = join('', <FILE>);
unless ($XML =~ /<type>turing<\/type>/) {
&kmyerror(2093, "This is not a Turing Machine");
}
unless ($XML =~ /<initial\/>/) {
&kmyerror(2099, "This does not have an initial state.");
}
unless ($XML =~ /<final\/>/) {
&kmyerror(2099, "This does not have a final state.");
}
$XML =~ s/ //g;
$XML =~ s/<state id="(\d+)">\s*<x>-?\d+\.\d+<\/x>\s*<y>-?\d+\.\d+<\/y>\s*(<label>(.*)<\/label>)?\s*(<initial\/>)?\s*(<final\/>)?\s*<\/state>/&makestate($1, $3, $4, $5)/ge;
$XML =~ s/<transition>\s*
<from>(\d+)<\/from>\s*
<to>(\d+)<\/to>\s*
(<read\/>|<read>(.*)<\/read>)\s*
(<write\/>|<write>(.*)<\/write>)\s*
<move>((L|R|S))<\/move>\s*
<\/transition>/&transition($1, $2, $4, $6, $7)/xge;
}
sub dohalt { local($String) = @_;
print "\n\nInput=$String\n";
print "Output=", join('', @TMTape), "\n";
if ($CurState == -1) {
print "System REJECTED, because of unspecified transition.\n";
}
}
sub printstate {
foreach $Char (0..$#TMTape) {
($Char == $HeadPos ? print 'V' : print ' ');
}
print "\n";
foreach $Char (@TMTape) {
if ($Char ne '') {
print $Char;
} else {
print '~';
}
}
print "\n";
print "St=$CurState Rd=$Read Nx=$Next Wr=$Write Mv=$Move\n";
print "\n\n";
}
sub simulatetm {
local($String, $Regexp, $ExpectedDecision) = @_;
local($TMDecision, $FinalState, $Next, $Write, $Move);
if ($Debug) {
print "Starting Simulation Group\n";
print "Starting with String $String\n";
print "Starting with Regexp $Regexp\n";
print "Starting with ExpectedDecision $ExpectedDecision\n";
}
@TMTape = split(//, $String);
unshift(@TMTape, '');
push(@TMTape, '');
$HeadPos = 1;
$CurState = $InitStateIndex;
if ($Debug) {
print "Setting Current State to initstateindex=$InitStateIndex\n";
} # only useful for tracing single program.
$TMDecision = 2;
$Feedback .= " $String ";
$TimeSteps = 0;
while($TMDecision == 2) {
foreach $FinalState (@FinalStateList) {
if ($FinalState == $CurState) {
$TMDecision = 1; # means terminate accept
$Feedback .= " accepted ";
}
}
if ($StepBound < ++$TimeSteps) {
$TMDecision = 3;
$Feedback .= " TERMINATED ";
if ($Debug) {
print "Terminating after numsteps=$TimeSteps\n";
} # only useful for tracing single program.
} elsif ($TMDecision != 1) {
$Read = $TMTape[$HeadPos];
if (! $Seen{$CurState}{$Read}) {
# no action specified
if ($Debug) {
print "No Action Specified for state=$State and read=<$Read>\n";
} # only useful for tracing single program.
$TMDecision = 0; # means terminate reject
$Feedback .= " rejected ";
# $Next = -1;
# $Write = $Read;
# $Move = 'S';
} else { # make the move
($Next, $Write, $Move) = @{$Transition{$CurState}{$Read}};
if ($Debug) { &printstate(); } # only useful for tracing single program.
$TMTape[$HeadPos] = $Write;
if ($Move eq 'R') {
$HeadPos++;
if ($HeadPos > $#TMTape) { push(@TMTape, ''); }
} elsif ($Move eq 'L') {
$HeadPos--;
if ($HeadPos < 0) {
unshift(@TMTape, '');
$HeadPos++;
}
}
$CurState = $Next;
}
}
}
$TapeString = join('', @TMTape);
if ($Debug) {
print "Ending Simulation Group\n";
print "Ending with FinalState $CurState\n";
print "Ending with Regexp $Regexp\n";
print "Ending with TapeString $TapeString\n";
print "Ending with TimeSteps $TimeSteps\n";
}
if ($TapeString =~ $Regexp) {
if ($ExpectedDecision == $TMDecision) {
$Feedback .= " correct // $Points\n";
if ($Debug) { print "Ending with correct decision\n"; }
return 1;
} else {
$Feedback .= " wrong // 0\n";
if ($Debug) { print "Ending with wrong decision\n"; }
return 0;
}
} else {
$Feedback .= " mismatch // 0\n";
if ($Debug) { print "Ending with tape mismatch\n"; }
return 0;
}
}
sub testtm {
local($Argument, $Regexp, $Decision, $Points) = @_;
$Total += $Points;
if (&simulatetm($Argument, $Regexp, $Decision)) { # the TM executed correctly, ...
$Score += $Points;
}
}
sub gradetm {
local ($DirPrefix, $Person, $ComSuffix) = @_;
local($FileName) = "$DirPrefix/$Person/$ComSuffix";
local($Points);
local($Login, $Submission) = ($Person =~ /^(.*)\.(\d)$/);
$Score = 0;
$Total = 0;
&readxmlfile($FileName);
# return;
$Feedback = '';
$Feedback .= "________________________________________________________________________\n";
$Feedback .= "\n LOGIN = $Login\n";
$Feedback .= "SUBMISSION = $Submission\n";
$Feedback .= "FILE = $FileName\n\n";
$Feedback .= "Termination occurs after $StepBound steps\n";
$Feedback .= "POINTS_____INPUT______RESULT________VERDICT______SCORE\n";
open(FILE, "< $TestFile");
while($Ln = <FILE>) {
chop($Ln);
($Argument, $Regexp, $Decision, $Points) =
($Ln =~ /^(\S+)\s+(\S+)\s+(\d+)\s+(\d+)$/);
$Feedback .= " $Points";
&testtm($Argument, $Regexp, $Decision, $Points);
}
close FILE;
if ($Total) {
$FinalScore = ($Score/$Total * 100);
$Feedback .= "\n***********************************\n";
$Feedback .= sprintf("********* SCORE = %d/%d = %.2f%\n", $Score, $Total, $FinalScore);
$Feedback .= "***********************************\n\n";
$Feedback .= "________________________________________________________________________\n";
print $Feedback;
printf REPORT $Feedback;
$LineFeedback = "$Login.$Submission";
$LineFeedback .= sprintf("--> %d/%d = %.2f%\n", $Score, $Total, $FinalScore);
printf REPORTA $LineFeedback;
} else {
print "I want to divide by zero\n";
}
# $SendCommand = "| /bin/mailx -s TMScores $StudentEmail{$Login}";
# print $SendCommand, "\n";
# if (1) { # Mail out results
# open(MAILOUT, $SendCommand);
# print MAILOUT $Feedback;
# close MAILOUT;
# }
}
($Debug, $DirPrefix, $FileNames, $ComSuffix, $TestFile, $OutFile) = @ARGV;
open(FILENAMES, "< $FileNames");
open(REPORT, "> $OutFile.long");
open(REPORTA, "> $OutFile.short");
while($FileName = <FILENAMES>) {
chop($FileName);
print $FileName, "\n";
&gradetm($DirPrefix, $FileName, $ComSuffix);
}
close FILENAMES;
close REPORT;
close REPORTA;
# issues of closure I have to make my thing such that it executes a maximum of 16000 states or something.