For one of my assignments I am supposed to write a Push Down Automaton. It's supposed to receive a string that has to be checked if it's an RNA Hairpin.
For example: gacgcaaguc would be one, since the gac is the opposite of the guc, and the four in the middle have to be either gcaa or gaaa.
I already have a working program which, however, checks each possible case. It has 15 if statements, one for each case, and I am sure there is a better way.
Now I am looking for a more elegant way in C++ to check these cases:
S -> aW1u | uW1a | gW1c | cW1g W1-> aW2u | uW2a | gW2c | cW2g W2-> aW3u | uW3a | gW3c | cW3g W3-> gW4a W4-> ca | aa As you probably know the right side gets filled into a Stack, and once I reach half the String, I check if the Stack and the other half of my String align. I didn't understand PDAs too well, so maybe you have some help for a guy who is new to this.
HPP:
#include <stack> class PDA { public: enum Language { HAIRPIN, // accepts RNA Hairpins BRACKETS // Zusatzaufgabe }; enum State { IN_PROGRESS = 0, // sequence is valid so far, but not complete SUCCESS = 1, // currently in accepting state, i.e. stack is empty after reading # symbol FAIL = 2 // sequence is not in language }; /// Constructor, which specifies which language to check (HAIRPIN by default) /// and internally builds up the production rules PDA(const Language l = Language::HAIRPIN); /// Read the next symbol and internally traverse states /// If a fail state was reached in the previous call, the fail state will be maintained /// @param a Symbol to read /// @return current state of PDA State next(const char a); /// Reset the automaton to a state as if newly constructed /// I.e. init stack and set state to s0. void reset(); protected: /// YOUR Member variables and functions State transitionfunction(char b, State cur, char stacktop); State current; std::stack<char> stark; int statechange; }; CPP:
#include <stack> #include "PDA.hpp" #include <iostream> using namespace std; PDA::PDA(const Language l) { current = IN_PROGRESS; stark.push('$'); statechange = 0; } PDA::State PDA::next(const char a) { if (statechange == 1) { if (stark.top() == '$') { return PDA::SUCCESS; } else if (stark.top() == a) { stark.pop(); return PDA::IN_PROGRESS; } else { return PDA::FAIL; } } else { return transitionfunction(a, current, stark.top()); } } void PDA::reset() { current = IN_PROGRESS; while (!stark.empty()) { stark.pop(); } stark.push('$'); statechange = 0; } PDA::State PDA::transitionfunction(const char b, PDA::State cur, const char stacktop) { if (cur == PDA::FAIL) { return PDA::FAIL; } else if (stacktop =='$') { if (b == 'a') { stark.push('u'); stark.push('1'); return PDA::IN_PROGRESS; } else if (b == 'c') { stark.push('g'); stark.push('1'); return PDA::IN_PROGRESS; } else if (b == 'g') { stark.push('c'); stark.push('1'); return PDA::IN_PROGRESS; } else if (b == 'u') { stark.push('a'); stark.push('1'); return PDA::IN_PROGRESS; } else { return PDA::FAIL; } } else if (stacktop =='1') { if (b == 'a') { stark.pop(); stark.push('u'); stark.push('2'); return PDA::IN_PROGRESS; } else if (b == 'c') { stark.pop(); stark.push('g'); stark.push('2'); return PDA::IN_PROGRESS; } else if (b == 'g') { stark.pop(); stark.push('c'); stark.push('2'); return PDA::IN_PROGRESS; } else if (b == 'u') { stark.pop(); stark.push('a'); stark.push('2'); return PDA::IN_PROGRESS; } else { return PDA::FAIL; } } else if (stacktop =='2') { if (b == 'a') { stark.pop(); stark.push('u'); stark.push('3'); return PDA::IN_PROGRESS; } else if (b == 'c') { stark.pop(); stark.push('g'); stark.push('3'); return PDA::IN_PROGRESS; } else if (b == 'g') { stark.pop(); stark.push('c'); stark.push('3'); return PDA::IN_PROGRESS; } else if (b == 'u') { stark.pop(); stark.push('a'); stark.push('3'); return PDA::IN_PROGRESS; } else { return PDA::FAIL; } } else if (stacktop == '3') { if(b == 'g'){ stark.pop(); stark.push('a'); stark.push('4'); return PDA::IN_PROGRESS; } else { return PDA::FAIL; } } else if (stacktop == '4') { if(b == 'c'){ stark.pop(); stark.push('a'); statechange = 1; return PDA::IN_PROGRESS; } else if(b == 'a') { stark.pop(); stark.push('a'); statechange = 1; return PDA::IN_PROGRESS; } else { return PDA::FAIL; } } } Main:
#include <iostream> #include "PDA.hpp" using namespace std; int main(int argc, char* argv[]) { if (argc != 2) { cout << "Please only enter one string" << endl; return 1; } string a = argv[1]; if (a.length() != 10) { cout << "The string should have length 10" << endl; return 1; } PDA::State final = PDA::IN_PROGRESS; PDA testpin; for (uint i = 0; i <= a.length(); i++) { final = testpin.next(a[i]); if (final == PDA::FAIL) { cout << "FAIL" << endl; return 1; } else if (final == PDA::SUCCESS) { cout << "ACCEPT" << endl; return 0; } } }