I’m stuck on Stage ##zm7
I’ve been trying for nearing a month now, and at this point, my code is of dubious quality at best.
The challenge is an absurd amount more difficult than all of the challenges before-hand, and ended up making me entirely refactor the entire codebase twice just to make it realistic. Not to say as a bad
thing per say, but I’m very much at my wit’s end with all the debugging. Right now, I think I’m in a spot where it’s nearly functional, but the code is rather strange.
I’ve got a regEx namespace containing all of the functions, and an Expression class containing the basic data: a string containing the original expression, and an int initialized with an enum to match an integer to each individual argument type. parenthesis-enclosed scopes and square bracket enclosed “any of” matches are both counted as a singular expression, as to allow me to iterate through the expressions without needing to search for the matching beginning. It’s ran linearly with a loop checking for matches by calling matchExpression(), unless either a postfix operator, scope operator, or “any of” operator is found, at which time it recursively runs the matchHere function. I wanted to mostly avoid recursion, but I for the life of me couldn’t figure out a way for those that weren’t far too verbose and complicated for my skill level.
I’ve noticed a primary issue for now: I can’t even begin to remember why as this has my brain fried at this point, but on the very last recursion before end of input, the iterator pointing to the current spot in input is not being incremented, leaving it to never reach the end, leaving it to never match the right-side anchor ($).
Sorry for being so verbose, but as I’ve said, I’m at my wit’s end here.
Here are my logs:
remote: [tester::#ZM7] ^[[0m$ echo -n "I see 1 cat, 2 dogs and 3 cows" | ./your_program.sh -E "^I see (\d (cat|dog|cow)s?(, | and )?)+$"
...
remote: [your_program] matchScope ((, | and )) - subscope of: " and " did not match.d. Returning false.
remote: [your_program] matchHere - new match entered.
remote: [your_program] matchHere - Full match. Returning true.
remote: [your_program] postfixZeroOrOne ((, | and )) - Found to be a zero-match. Returning true.
remote: [your_program] matchHere - Match. Continueing...
remote: [your_program] matchHere - Full match. Returning true.
remote: [your_program] postfixZeroOrOne (s) - Found to be a one-match. Returning true.
remote: [your_program] matchHere - Match. Continueing...
remote: [your_program] matchHere - Full match. Returning true.
remote: [your_program] matchScope ((\d (cat|dog|cow)s?(, | and )?)) - subscope of: "\d (cat|dog|cow)s?(, | and )?" match found. Returning true with a current match of: 'postfixOneOrMore ((\d (cat|dog|cow)s?(, | and )?)) - checking possible match: 's'.
... (After the program tried incrementing the starting point forward a few times.)
remote: [your_program] matchHere - Matching expression: $ (8)
remote: [your_program] matchHere - with starting character: 1
remote: [your_program] matchExpression - No postfix found. Expression: $ (8)
remote: [your_program] matchHere - No match. Returning false.
remote: [your_program] matchHere - No match. Returning false.
remote: [tester::#ZM7] Expected exit code 0, got 1
remote: [tester::#ZM7] Test failed
Sorry for so much text in there, too. I ended up going mad with couts just to try and find what was wrong.
And here’s a snippet of my code:
bool regEx::matchPattern(const std::string& pattern, const std::string& text){
const std::vector<Expression> expressions = parsePattern(pattern);
std::vector<Expression>::const_iterator exp = expressions.cbegin();
std::vector<Expression>::const_iterator end = expressions.cend();
std::cout << "matchPattern - Match pattern called with a pattern of: \"" << pattern << "\" \nmatchPattern - And a string input of: \"" << text << "\"" << std::endl;
std::string::const_iterator textBegin = text.begin();
std::string::const_iterator match = text.begin();
if((*exp).type == Expression::ANCHOR_START){
std::cout << "Pattern is left-anchored. Testing from start..." << std::endl;
++exp;
return matchHere(exp, end, match);
}
std::cout << "matchPattern - Pattern is not left-anchored. Testing from each index..." << std::endl;
int debugIndex = 0;
while(*textBegin!= '\0'){
std::cout << "matchPattern - Testing from character: '" << *match << "' at index: " << debugIndex++ << std::endl;
if (matchHere(exp, end, match))
return true;
if(*textBegin == '\0')
return false;
++textBegin;
match = textBegin;
exp = expressions.cbegin();
}
return false;
}
bool regEx::matchHere(std::vector<Expression>::const_iterator& exp, const std::vector<Expression>::const_iterator& end, std::string::const_iterator& match){
std::string::const_iterator textCurr = match;
std::cout << "matchHere - new match entered." << std::endl;
while(exp != end){
std::cout << "matchHere - Matching expression: " << (*exp).typeString << " (" << (*exp).type << ")\n"
<< "matchHere - with starting character: " << *textCurr << std::endl;
if (matchExpression(exp, end, textCurr)){
std::cout << "matchHere - Match. Continueing..." << std::endl;
++exp;
++textCurr;
continue;
}
break;
}
bool regEx::matchExpression(std::vector<Expression>::const_iterator& exp, const std::vector<Expression>::const_iterator& end, std::string::const_iterator& match){
if (exp + 1 != end){
switch((*(exp + 1)).type){
case Expression::MATCH_ONE_OR_MORE:
std::cout << "matchExpression - One or More (+) postfix found. Processing postfix." << std::endl;
return postfixOneOrMore(exp, end, match);
case Expression::MATCH_ZERO_OR_ONE:
std::cout << "matchExpression - Zero or one (?) postfix found. Processing postfix." << std::endl;
return postfixZeroOrOne(exp, end, match);
default:
break;
}
}
if(exp == end){ //If end of scope was reached, success. All match.
std::cout << "matchHere - Full match. Returning true." << std::endl;
match = textCurr;
return true;
}
std::cout << "matchHere - No match. Returning false." << std::endl;
return false;
}
std::cout << "matchExpression - No postfix found. Expression: " << (*exp).typeString << " (" << (*exp).type << ")" << std::endl;
switch((*exp).type){
case Expression::EXACT:
return (*exp).typeString[0] == *match;
case Expression::DIGIT:
return std::isdigit(*match);
case Expression::WORD:
return std::isalnum(*match) || *match == '_';
case Expression::ANY:
return (*match) != '\0';
case Expression::ANY_OF:
return matchAnyOf(*exp, match);
case Expression::SCOPE:
return matchScope(*exp, match);
case Expression::ANCHOR_END:
return (exp + 1) == end && *match == '\0';
default:
return false;
}
}
bool regEx::postfixZeroOrOne(std::vector<Expression>::const_iterator& exp, const std::vector<Expression>::const_iterator& end, std::string::const_iterator& match){
std::cout << "postfixZeroOrOne (" << (*exp).typeString << ") - entered." << std::endl;
std::vector<Expression>::const_iterator nextExp = exp + 2;
std::string::const_iterator currMatch = match;
if(matchExpression(exp, exp + 1, currMatch)){
std::string::const_iterator tempMatch = currMatch + 1;
if (matchHere(nextExp, end, tempMatch)){
std::cout << "postfixZeroOrOne (" << (*exp).typeString << ") - Found to be a one-match. Returning true." << std::endl;
match = tempMatch - 1;
exp = end - 1;
return true;
}
}
if (matchHere(nextExp, end, currMatch)){
std::cout << "postfixZeroOrOne (" << (*exp).typeString << ") - Found to be a zero-match. Returning true." << std::endl;
match = currMatch - 1;
exp = end - 1;
return true;
} else {
currMatch = match;
}
std::cout << "postfixZeroOrOne (" << (*exp).typeString << ") - No match found. Returning false." << std::endl;
return false;
}
If you need any other functions just ask. The writing quality fell off drastically after the first week, and at this point nothing’s really even decent, but I’m determined to get this done.