Domanda

I need to design a Turing Machine Simulator in C++ that takes in an input file that goes something like this:

Q:q1,q2,q3,q4
A:0,1
Z:0,1,x
T:q1,0,q2,x,R
T:q1,1,q2,x,R
T:q2,0,q2,0,R
...
S:q1
F:q3,q4

Where Q is states, A is input values, Z is tape alphabet, S is start state, F is accept and reject states.

It needs to handle an input where it takes in the number of inputs, the input strings and accept or reject.

So if it input is:
3
0,#,1,1
1,1
0,1,0

the output would print out the steps and whether it accepts or rejects.

I need to create a TM that performs arithmetic operations, one that performs string operations, and another of my choice.

Any help on how to get started is appreciated.

È stato utile?

Soluzione

Try something like this:

#include <iostream>
#include <string.h>
#include <vector>
#include <fstream>
#include <cstdlib>
#include <stdio.h>
#include "tm.h"

using namespace std;

tm::tm(char *fn)
{
    current = "";
    readFile(fn);
}

void tm::readFile(char *fn)
{
    char temp;
    string word = "";
    ifstream indata;
    bool blank = false;
    indata.open(fn); //opens the file
    if(!indata) //error message if the file is unable to be opened
    {   
        cout << "Could not open the specified file \"" << fn << "\"" << endl;
        exit(1);
    }
    indata >> temp;
    while (!indata.eof())
    {
        if (temp == 'Q')
        {
            //cout << "Q" << endl;
            indata >> temp;
            indata >> temp; //skip the :
            while (temp != 'A')
            {
                if (temp != ',') word += temp;
                else
                {
                    QQ.push_back(word);
                    word = "";
                }
                indata >> temp;
            }
            QQ.push_back(word);
            word = "";
        }
        else if (temp == 'A')
        {
            //cout << "A" << endl;
            indata >> temp;
            indata >> temp; //skip the :
            while (temp != 'Z')
            {
                if (temp != ',') word += temp;
                else
                {
                    AA.push_back(word);
                    word = "";
                }
                indata >> temp;
            }
            AA.push_back(word);
            word = "";
        }
        else if (temp == 'Z')
        {
            //cout << "Z" << endl;
            indata >> temp;
            indata >> temp; //skip the :
            while (temp != 'T')
            {
                if (temp != ',') word += temp;
                else
                {
                    ZZ.push_back(word);
                    word = "";
                }
                indata >> temp;
            }
            ZZ.push_back(word);
            word = "";
            for (int i = 0; i < (int)ZZ.size(); i++)
                if (ZZ[i].compare(" ") == 0)
                    blank = true;
            if (blank == false) //no blanks were found in the tape alphabet
                ZZ.push_back(" ");
        }
        else if (temp == 'T')
        {
            //cout << "T" << endl;
            indata >> temp;
            indata >> temp; //skip the :
            bool wasComma = false;
            vector<string> row;
            while (temp != 'T' && temp != 'S')
            {
                if (wasComma && temp == ',') //the last one was a comma
                {
                    row.push_back(" ");
                    wasComma = false;
                }
                else if (temp != ',')
                {
                    word += temp;
                    wasComma = false;
                }
                else
                {
                    row.push_back(word);
                    word = "";
                    wasComma = true;
                }
                indata >> temp;
            }
            row.push_back(word);
            TT.push_back(row);
            word = "";
        }
        else if (temp == 'S')
        {
            //cout << "S" << endl;
            indata >> temp;
            indata >> temp; //skip the :
        while (temp != 'F')
            {
                if (temp != ',') word += temp;
                else
                {
                    SS = word;
                    word = "";
                }
                indata >> temp;
            }
            SS = word;
            word = "";
        }
        else if (temp == 'F')
        {
            //cout << "F" << endl;
            indata >> temp;
            indata >> temp; //skip the :
            while (!indata.eof())
            {
                if (temp != ',')
                    word += temp;
                else
                {
                    FF.push_back(word);
                    word = "";
                }
                indata >> temp;
            }
            FF.push_back(word);
            word = "";
        }
    }   
    indata.close();
    readInput();
    runAll();
    return;
}

void tm::readInput()
{
    int num, k;
    cin >> num;

    string temp;
    getline(cin,temp);
    getline(cin,temp);
    for (int i = 0; i < num; i++) //num is the number of rows of input to the machine
{
        vector<string> row;
        string word = "";
        for(k = 0; k < (int)temp.size(); k++)
        {
            if (temp[k] != ',')
                word += temp[k];
            else if ((int)word.size() > 0)
            {
                row.push_back(word);
                word = "";
            }
            if (k == (int)temp.size() -1 && (int)word.size() > 0)
            {
                row.push_back(word);
                word = "";
            }
    }
        if (k > 0)
            input.push_back(row);
        else //if there is an empty row of input to the machine
        {
            vector<string> row;
            row.push_back("e");
            input.push_back(row);
        }
        getline(cin,temp);
    }

    return;
}

void tm::runAll()
{
    checkForAlphabetBlanks();
    checkTransitions();
    checkStart();
    checkFinal();
    checkDeterministic();
    checkAcceptReject();
    checkInput();

    int currentPosition;
    string currentState, currentSymbol;
    bool found, first = true;
    for (int i = 0; i < (int)input.size(); i++) //for each row of the input
    {
        if (first != true)
            cout << endl;
        first = false;
        currentPosition = 0;
        currentState = SS;
        for (int k = 0; k < 1000; k++) //for each character of input, then up to 1000
        {
            if (k == 0) //the first time
            {
                if (0 < (int)input[i].size()) //we are not past the right of the tape
                    currentSymbol = input[i][0];
                else
                    currentSymbol = " ";
                cout << "()" << SS << "(";
                for (int g = 0; g < (int)input[i].size(); g++)
                {
                    cout << input[i][g];
                    if (g != (int)input[i].size() - 1) //it is not the last input
                        cout << ",";
                    else
                        cout << ")" << endl;
                }
            }
            if (currentState.compare(FF[0]) == 0) //check if we are accept
            {
                cout << "ACCEPT" << endl;
                break;
            }
            else if (currentState.compare(FF[1]) == 0) //check if we are reject
            {
                cout << "REJECT" << endl;
                break;
            }
            found = false;
            for (int g = 0; g < (int)TT.size(); g++)
            {
                if (TT[g][0].compare(currentState) == 0 && TT[g][1].compare(currentSymbol) == 0) //same state and symbol as the transition line
                {
                    found = true;
                    currentState = TT[g][2];
                    input[i][currentPosition] = TT[g][3];
                    if (TT[g][4].compare("R") == 0) currentPosition++;
                    else currentPosition--;
                    //check for out of bounds to the left
                    if (currentPosition < 0) currentPosition = 0;
                    cout << "(";
                    for (int t = 0; t < currentPosition; t++)
                    {
                        cout << input[i][t];
                        if (t != currentPosition - 1) cout << ","; //not the last one
                    }
                    cout << ")" << currentState << "(";
                    for (int t = currentPosition; t < (int)input[i].size(); t++)
                    {
                        cout << input[i][t];
                        if (t != (int)input[i].size() - 1) cout << ","; //not the last one
                    }
                    cout << ")" << endl;
                    if (currentPosition < (int)input[i].size()) currentSymbol = input[i][currentPosition]; //not past the right side of the tape
                    else
                    {
                        currentSymbol = " ";
                        input[i].push_back(" ");
                    }
                    break;
                }
            }
            if (found == true) //a transition was found
            {
                if (currentState.compare(FF[0]) == 0) //check if accept
                {
                    cout << "ACCEPT" << endl;
                    break;
                }
                else if (currentState.compare(FF[1]) == 0) //check if reject
                {
                    cout << "REJECT" << endl;
                    break;
                }
            }
            else
            {
                currentPosition++;
                cout << "(";
                for (int t = 0; t < currentPosition; t++)
                {
                    cout << input[i][t];
                    if (t != currentPosition - 1) cout << ","; //not the last one
                }
                cout << ")" << FF[1] << "(";
                for (int t = currentPosition; t < (int)input[i].size(); t++)
                {
                    cout << input[i][t];
                    if (t != (int)input[i].size() - 1) cout << ","; //not the last one
                }
                cout << ")" << endl;
                cout << "REJECT" << endl;
                break;
            }
            if (k == 999)
                cout << "DID NOT HALT" << endl;
        }
    }

    return;
}

void tm::checkForAlphabetBlanks()
{
    for (int i = 0; i < (int)AA.size(); i++)
    {
        if (AA[i].compare(" ") == 0)
        {
            cout << "The alphabet has a blank space." << endl;
            exit(1);
        }
    }
    return;
}

void tm::checkTransitions()
{
    bool state1, state2, character1, character2;

    for (int i = 0; i < (int)TT.size(); i++)
    {
    //check the direction
        if (TT[i][4].compare("R") != 0 && TT[i][4].compare("L") != 0)
        {
            cout << "The only valid directions are R and L." << endl;
            exit(1);
        }
        //check the states
        state1 = false; state2 = false;
        for (int k = 0; k < (int)QQ.size(); k++)
        {
            if (TT[i][0].compare(QQ[k]) == 0) state1 = true;
            if (TT[i][2].compare(QQ[k]) == 0) state2 = true;
        }
        if (state1 == false)
        {
            cout << "The state " << TT[i][0] << " in transition function number " << i << " is not in the list of states." << endl;
            exit(1);
        }
        if (state2 == false)
        {
            cout << "The state " << TT[i][2] << " in transition function number " << i << " is not in the list of states." << endl;
            exit(1);
        }
        //check the characters
        character1 = false; character2 = false;
        for (int k = 0; k < (int)ZZ.size(); k++)
        {
            if (TT[i][1].compare(ZZ[k]) == 0) character1 = true;
            if (TT[i][3].compare(ZZ[k]) == 0) character2 = true;
        }
        if (character1 == false)
        {
            cout << "The character '" << TT[i][1] << "' in transition function number " << i << " is not in the tape alphabet." << endl;
            exit(1);
        }
        if (character2 == false)
        {
            cout << "The character '" << TT[i][3] << "' in transition function number " << i << " is not in the tape alphabet." << endl;
            exit(1);
        }
}
    return;
}

void tm::checkStart()
{
    bool in = false;
    for (int i = 0; i < (int)QQ.size(); i++)
    {
        if (SS.compare(QQ[i]) == 0) in = true;
    }
    if (in == false)
    {
        cout << "The start state " << SS << " is not in the list of states." << endl;
        exit(1);
    }
}

void tm::checkFinal()
{
    if (FF[0].compare(FF[1]) == 0)
    {
        cout << "The accept and reject states cannot be the same." << endl;
        exit(1);
    }
    bool accept = false, reject = false;
    for (int i = 0; i < (int)QQ.size(); i++)
    {
        if (FF[0].compare(QQ[i]) == 0) accept = true;
        if (FF[1].compare(QQ[i]) == 0) reject = true;
        }
        if (accept == false)
        {
        cout << "The accept state " << FF[0] << " is not in the list of states." << endl;
        exit(1);
    }
    if (reject == false)
    {
        cout << "The reject state " << FF[1] << " is not in the list of states." << endl;
        exit(1);
    }
}

void tm::checkDeterministic()
{
    for (int i = 0; i < (int)TT.size(); i++)
        for (int k = i+1; k < (int)TT.size(); k++)
            if (TT[i][0].compare(TT[k][0]) == 0 && TT[i][1].compare(TT[k][1]) == 0)
            {
            cout << "The machine cannot proceed deterministically, transitions " << i << " and " << k << " are the same." << endl;
            exit(1);
        }
}

void tm::checkAcceptReject()
{
    for (int i = 0; i < (int)TT.size(); i++)
    {
        if (TT[i][0].compare(FF[0]) == 0 || TT[i][0].compare(FF[1]) == 0)
        {
            cout << "The machine cannot transitions from the accept or reject states." << endl;
        }
    }
}

void tm::checkInput()
{
    bool exists;
    for (int i = 0; i < (int)input.size(); i++)
    {
        for (int k = 0; k < (int)input[i].size(); k++)
        {
            exists = false;
            for (int g = 0; g < (int)AA.size(); g++)
            {
                if (input[i][k].compare(AA[g]) == 0) exists = true;
            }
            if (exists == false)
            {
                if (input[i][0].compare("e") != 0) //it is not 'e'
                {
                    cout << "The input character " << input[i][k] << " is not in the input alphabet." << endl;
                    exit(1);
                }
            }
        }
    }
}

Altri suggerimenti

You can to mimic a file compressor: it is given a string of characters and compresses repetitive sequences into groups of 8 (adding larger groups would take a linear amount of more lines of code, adding more characters would take an exponential amount of more lines of code due to each letter needing to react to each possible letter.)

The machine notes the front of the tape, then runs all the way to the back. it 'eats' characters, putting like characters into an enlarging pool. When the limit is reached, the end of the tape is reached, or another character type is reached, the machine prints how far it has come, then starts piling up the new characters.

Q:q0,q1,q2,Fs,Rs,a1,a1z,a2,a2z,a3,a3z,a4,a4z,a5,a5z,a6,a6z,a7,a7z,b1,b1y,b2,b2y,b3,b3y,b4,b4y,b5,b5y,b6,b6y,b7,b7y
A:a,b
Z: ,a,a2,a3,a4,a5,a6,a7,a8,b,b2,b3,b4,b5,b6,b7,b8,y,z 
T:q0,a,q1,y,R
T:q0,b,q1,z,R   
T:q1,a,q1,a,R
T:q1,b,q1,b,R
T:q1, ,q2, ,L    
T:q2,a,a1, ,L
T:q2,b,b1, ,L
T:q2,y,Fs,a,R
T:q2,z,Fs,b,R  
T:a1,a,a2, ,L
T:a1,b,b1,a,L
T:a1,y,Fs,a2,R
T:a1,z,a1z,b,R
T:a1z, ,Fs,a,R    
T:b1,b,b2, ,L
T:b1,a,a1,b,L
T:b1,z,Fs,b2,R
T:b1,y,b1y,a,R
T:b1y, ,Fs,b,R    
T:a2,a,a3, ,L
T:a2,b,b1,a2,L
T:a2,y,Fs,a3,R
T:a2,z,a2z,b,R
T:a2z, ,Fs,a2,R    
T:b2,b,b3, ,L
T:b2,a,a1,b2,L
T:b2,z,Fs,b3,R
T:b2,y,b2y,a,R
T:b2y, ,Fs,b2,R   
T:a3,a,a4, ,L
T:a3,b,b1,a3,L
T:a3,y,Fs,a4,R
T:a3,z,a3z,b,R
T:a3z, ,Fs,a3,R   
T:b3,b,b4, ,L
T:b3,a,a1,b3,L
T:b3,z,Fs,b4,R
T:b3,y,b3y,a,R
T:b3y, ,Fs,b3,R   
T:a4,a,a5, ,L
T:a4,b,b1,a4,L
T:a4,y,Fs,a5,R
T:a4,z,a4z,b,R
T:a4z, ,Fs,a4,R 
T:b4,b,b5, ,L
T:b4,a,a1,b4,L
T:b4,z,Fs,b5,R
T:b4,y,b4y,a,R
T:b4y, ,Fs,b4,R  
T:a5,a,a6, ,L
T:a5,b,b1,a5,L
T:a5,y,Fs,a6,R
T:a5,z,a5z,b,R
T:a5z, ,Fs,a5,R   
T:b5,b,b6, ,L
T:b5,a,a1,b5,L
T:b5,z,Fs,b6,R
T:b5,y,b5y,a,R
T:b5y, ,Fs,b5,R    
T:a6,a,a7, ,L
T:a6,b,b1,a6,L
T:a6,y,Fs,a7,R
T:a6,z,a6z,b,R
T:a6z, ,Fs,a7,R   
T:b6,b,b7, ,L
T:b6,a,a1,b6,L
T:b6,z,Fs,b7,R
T:b6,y,b6y,a,R
T:b6y, ,Fs,b7,R
T:a7,a,q2,a8,L
T:a7,b,b1,a7,L
T:a7,y,Fs,a8,R
T:a7,z,a7z,b,R
T:a7z, ,Fs,a7,R
T:b7,b,q2,b8,L
T:b7,a,a1,b8,L
T:b7,z,Fs,b8,R
T:b7,y,b7y,a,R
T:b7y, ,Fs,b7,R

S:q0
F:Fs,Rs

You can mimic the reading of RNA base pairs to create amino acids in cellular biology. The user gives a string of characters consisting exclusively of a,c,g and u. The machine reads down the line until it reads the start codon "a,u,g", at which point it begins translating the RNA into amino acids. it does this until it reaches the end of the string or until a stop codon is reached ("UAA", "UGA", "UAG"). If it reaches a stop codon, it continues down the string until it reads another start codon or the string terminates. Reading any amino acid sequence results in an accept, and it is not necessary to reach a stop codon (as in biology). However, a string with no start codon will result in a reject statement.

The first example demonstrates a several character delay, a start codon, then amino acids until a stop codon, then more unused characters, then completion. The second example demonstrates a start codon, middle codons, a stop codon, filler, another start codon, and codons until string completion The third example demonstrates no start codon and a REJECT state.

Q:q0,q1,q2,q3,q4,q5,q6,Fs,Rs,s1,s2,u,c,a,g,uu,ua,ug,ca,au,aa,ag,ga
A:u,c,a,g,u
Z: ,u,c,a,g,ala,arg,asn,asp,cys,gln,glu,gly,his,ile,leu,lem,lys,met,phe,pro,ser,thr,trp,tyr,val,stop

T:q0,u,q0, ,R
T:q0,c,q0, ,R
T:q0,g,q0, ,R
T:q0,a,q1, ,R

T:q1,c,q0, ,R
T:q1,g,q0, ,R
T:q1,a,q0, ,R
T:q1,u,q2, ,R

T:q2,u,q0, ,R
T:q2,c,q0, ,R
T:q2,a,q0, ,R
T:q2,g,q3,met,R

T:q4,u,q4, ,R
T:q4,c,q4, ,R
T:q4,g,q4, ,R
T:q4,a,q5, ,R
T:q4, ,Fs, ,R

T:q5,c,q4, ,R
T:q5,g,q4, ,R
T:q5,a,q4, ,R
T:q5,u,q6, ,R
T:q5, ,Fs, ,R

T:q6,u,q4, ,R
T:q6,c,q4, ,R
T:q6,a,q4, ,R
T:q6,g,q3,met,R
T:q6, ,Fs, ,R

T:s1,u,q3, ,R
T:s1,c,q3, ,R
T:s1,a,q3, ,R
T:s1,g,q3, ,R
T:s1, ,s2, ,L

T:s2,ala,Fs, ,R
T:s2,arg,Fs, ,R
T:s2,gly,Fs, ,R
T:s2,leu,Fs, ,R
T:s2,pro,Fs, ,R
T:s2,ser,Fs, ,R
T:s2,thr,Fs, ,R
T:s2,val,Fs, ,R

T:q3,u,u, ,R
T:q3,c,c, ,R
T:q3,a,a, ,R
T:q3,g,g, ,R
T:q3, ,Fs, ,R

T:u,u,uu, ,R
T:u,c,s1,ser,R
T:u,a,ua, ,R
T:u,g,ug, ,R
T:u, ,Fs, ,R

T:uu,u,q3,phe,R
T:uu,c,q3,phe,R
T:uu,a,q3,leu,R
T:uu,g,q3,leu,R
T:uu, ,Fs, ,R

T:ua,u,q3,tyr,R
T:ua,c,q3,tyr,R
T:ua,a,q4,stop,R
T:ua,g,q4,stop,R
T:ua, ,Fs, ,R

T:ug,u,q3,cys,R
T:ug,c,q3,cys,R
T:ug,a,q4,stop,R
T:ug,g,q3,trp,R
T:ug, ,Fs, ,R

T:c,u,s1,leu,R
T:c,c,s1,pro,R
T:c,a,ca, ,R
T:c,g,s1,arg,R
T:c, ,Fs, ,R

T:ca,u,q3,his,R
T:ca,c,q3,his,R
T:ca,a,q3,gln,R
T:ca,g,q3,gln,R
T:ca, ,Fs, ,R

T:a,u,au, ,R
T:a,c,s1,thr,R
T:a,a,aa, ,R
T:a,g,ag, ,R
T:a, ,Fs, ,R

T:au,u,q3,ile,R
T:au,c,q3,ile,R
T:au,a,q3,ile,R
T:au,g,q3,met,R
T:au, ,Fs, ,R

T:aa,u,q3,asn,R
T:aa,c,q3,asn,R
T:aa,a,q3,lys,R
T:aa,g,q3,lys,R
T:aa, ,Fs, ,R

T:ag,u,q3,ser,R
T:ag,c,q3,ser,R
T:ag,a,q3,arg,R
T:ag,g,q3,arg,R
T:ag, ,Fs, ,R

T:g,u,s1,val,R
T:g,c,s1,ala,R
T:g,a,ga, ,R
T:g,g,s1,gly,R
T:g, ,Fs, ,R

T:ga,u,q3,asp,R
T:ga,c,q3,asp,R
T:ga,a,q3,glu,R
T:ga,g,q3,glu,R
T:ga, ,Fs, ,R

S:q0
F:Fs,Rs
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top