//  filename    : TestKrimskramsLBSWL.cpp
//	description : Test for Krimskrams Looping Back To Start Of While Loop, main
//	author      : Karlheinz Hug
//	date        : 2010-12-20
//	revision    : 2010-12-21

#include <iostream>
#include <string>

using namespace ::std;

	bool check1(string way)  
	{  
		string copy = way;  
		while(copy.size()>=0)  
		{  
			if(copy == "")  
				return true;  
			if(copy.size() == 1)  
				return false;  
			if(copy.at(0) == 'n' || copy.at(0) == 'N' || copy.at(0) == 's' || copy.at(0) == 'S' || copy.at(0) == 'e' || copy.at(0) == 'E' || copy.at(0) == 'w' || copy.at(0) == 'W')  
			{  
				if(isdigit(copy.at(1)))  
				{  
					if(isdigit(copy.at(2)))  
					{  
						copy = copy.substr(0,2);  
										   //HERE  
					}  
					else 
					{  
						copy = copy.substr(0,1);  
							//HERE  
									}  
					return true;  
				}  
				else 
					return false;  
			}  
			else 
				return false;  
		}  
	} 

	bool check2 (string way) {  
		string copy = way;  
		while (copy.size() >= 0) {  
			if (copy == "")  
				return true;  
			if (copy.size() == 1)  
				return false;  
			if (copy.at(0) == 'n' || copy.at(0) == 'N' || copy.at(0) == 's' || copy.at(0) == 'S' ||
				copy.at(0) == 'e' || copy.at(0) == 'E' || copy.at(0) == 'w' || copy.at(0) == 'W') {  
				if (isdigit(copy.at(1))) {  
					if (isdigit(copy.at(2))) {  
						copy = copy.substr(0, 2);  
						continue; 
					} else {  
						copy = copy.substr(0, 1);  
						continue; 
					}  
					return true;  
				} else 
					return false;  
			} else 
				return false;  
		}  
	} 

	bool check3 (string way) {  
		while (true) {  
			if (way == "")  
				return true;  
			if (way.size() == 1)  
				return false;  
			if (way.at(0) == 'n' || way.at(0) == 'N' || way.at(0) == 's' || way.at(0) == 'S' ||
				way.at(0) == 'e' || way.at(0) == 'E' || way.at(0) == 'w' || way.at(0) == 'W') {  
				if (isdigit(way.at(1))) {  
					if (isdigit(way.at(2))) {  
						way = way.substr(0, 2);  
					} else {  
						way = way.substr(0, 1);  
					}  
					continue;  
				} else 
					return false;  
			} else 
				return false;  
		}  
	} 
	
	bool isGoodLetter (char c) {
		c = tolower(c);
		return c == 'n' || c == 's' || c == 'e' || c == 'w';
	}
	
	bool check4 (string way) {  
		while (true) {  
			if (way == "")  
				return true;  
			if (way.size() == 1)  
				return false;  
			if (isGoodLetter(way.at(0))) {  
				if (isdigit(way.at(1))) {  
					if (isdigit(way.at(2))) {  
						way = way.substr(0, 2);  
					} else {  
						way = way.substr(0, 1);  
					}  
					continue;  
				} else 
					return false;  
			} else 
				return false;  
		}  
	} 		

	bool check5 (string way) {  
		while (true) {  
			if (way == "")  
				return true;  
			if (way.size() == 1)  
				return false;  
			if (!isGoodLetter(way.at(0))) 
				return false;  
			else if (!isdigit(way.at(1))) 
				return false;  
			else {
				if (isdigit(way.at(2))) {  
					way = way.substr(0, 2); 
				} else {  
					way = way.substr(0, 1);  
				}  
				continue;  
			}  
		}  
	} 

	bool check6 (string way) {  
		while (true) {  
			if (way == "")  
				return true;  
			if (way.size() == 1)  
				return false;  
			if (!isGoodLetter(way.at(0))) 
				return false;  
			else if (!isdigit(way.at(1))) 
				return false;  
			else if (isdigit(way.at(2))) 
				way = way.substr(0, 2); 
			else 
				way = way.substr(0, 1);  
		}  
	} 

	bool check7 (string way) {  
		while (true) {  
			if (way == "")  
				return true;  
			else if (way.size() == 1)  
				return false;  
			else if (!isGoodLetter(way.at(0))) 
				return false;  
			else if (!isdigit(way.at(1))) 
				return false;  
			else if (isdigit(way.at(2))) 
				way = way.substr(0, 2); 
			else 
				way = way.substr(0, 1);  
		}  
	} 

	bool check8 (string way) {  
		while (true) {  
			if (way == "")  
				return true;  
			else if (way.size() == 1 || !isGoodLetter(way.at(0)) || !isdigit(way.at(1))) 
				return false;  
			else if (isdigit(way.at(2))) 
				way = way.substr(0, 2); 
			else 
				way = way.substr(0, 1);  
		}  
	} 

	bool check9 (string way) {  
		while (way.size() > 1 && isGoodLetter(way.at(0)) && isdigit(way.at(1))) { 
			way = way.substr(0, (isdigit(way.at(2)) ? 2 : 1));
		} 
		return way.size() == 0;
	} 

	bool check10 (string way) {  
		while (way.size() > 1 && isGoodLetter(way.at(0)) && isdigit(way.at(1))) { 
			way = way.substr(0, (way.size() > 2 && isdigit(way.at(2)) ? 2 : 1));
		} 
		return way.size() == 0;
	} 

	bool check11 (string w) {  
		return w == "";
	} 

	bool check12 (string way) {  
		while (way.size() > 1 && isGoodLetter(way.at(0)) && isdigit(way.at(1))) { 
			way = way.substr(way.size() > 2 && isdigit(way.at(2)) ? 3 : 2);
		} 
		return way.size() == 0;
	} 

	// Specification by EBNF-rules:
	// Way       = { Direction digit [ digit ] } .
	// Direction = 'n' | 'N' | 's' | 'S' | 'e' | 'E' | 'w' | 'W' .
	
	bool isDirection (char c) {
		c = tolower(c);
		return c == 'n' || c == 's' || c == 'e' || c == 'w';
	}
	
	bool isWay13 (string s) {  
		while (s.size() > 1 && isDirection(s.at(0)) && isdigit(s.at(1))) { 
			s = s.substr(s.size() > 2 && isdigit(s.at(2)) ? 3 : 2);
		} 
		return s.size() == 0;
	} 

	bool isWay14 (const string & s) {  
		int i = 0;
		while (i + 1 < s.size() && isDirection(s.at(i)) && isdigit(s.at(i + 1))) { 
			i += (i + 2 < s.size() && isdigit(s.at(i + 2)) ? 3 : 2);
		} 
		return i >= s.size();
	} 

	bool isWay15 (const string & s) {  
		int i = 0;
		while (i + 1 < s.size() && isDirection(s[i]) && isdigit(s[i + 1])) { 
			i += (i + 2 < s.size() && isdigit(s[i + 2]) ? 3 : 2);
		} 
		return i >= s.size();
	} 
	
	void test_val_par 
        (const string & name, bool (*check) (string way), string way) {
        cout << name << "(\"" << way << "\") = ";
        try {
            cout << check(way);
        } catch (exception e) {
            cout << e.what();
        }
        cout << endl;
    }

	void test_ref_par 
        (const string & name, bool (*check) (const string & way), const string & way) {
        cout << name << "(\"" << way << "\") = ";
        try {
            cout << check(way);
        } catch (exception e) {
            cout << e.what();
        }
        cout << endl;
    }

	void test_all (const string & way) {
         test_val_par ("check1", check1, way);
         test_val_par ("check2", check2, way);
         test_val_par ("check3", check3, way);
         test_val_par ("check4", check4, way);
         test_val_par ("check5", check5, way);
         test_val_par ("check6", check6, way);
         test_val_par ("check7", check7, way);
         test_val_par ("check8", check8, way);
         test_val_par ("check9", check9, way);
         test_val_par ("check10", check10, way);
         test_val_par ("check11", check11, way);
         test_val_par ("check12", check12, way);
         test_val_par ("isWay13", isWay13, way);
         test_ref_par ("isWay14", isWay14, way);
         test_ref_par ("isWay15", isWay15, way);
    }

	int main (int argc, char * argv[]) {
		test_all ("");
		test_all ("x");
		test_all ("n");
		test_all ("n1");
		test_all ("N1x");
		test_all ("e12");
		test_all ("E23x");
		test_all ("E23w");
		test_all ("E23w4");
		test_all ("E23W45");
		test_all ("E23W45s");
		test_all ("E23W45s78");
		return 0;
	}

