The purpose: This function parses through a string trie following the path that matches an input string of characters. When all the char in the string are parsed, true is returned. I want to step over a char and return if there is still a valid path.
The application: the strings are a location hierarchy for a highway project. So, project 5 has an alignment C, that has an offset of N and a workzone 3; 5CN3. But, sometimes I want to define a string for all child locations for a project task that covers all the locations. So, '0' is all locations; for a half day operation like grade dirt has no workzones - all the so to represent this task is all workzones in the north alignment C; 5CN0. same for if an operation covers the whole project; 5000.
Approaches: I could have used a wildcard '?' function but I want to keep this specific step over for the purpose of abstracting the locations. Maybe '?' is the right approach, but seems to loose some control. Also, this could be written without the for loop and use a position index parameter; maybe that is where this goes wrong - maybe on backtracking.
Code: nodeT is the trie nodes, word is the input string, this function is a bool and returns 1/0 if the string path exists.
bool Lexicon::containsWordHelper(nodeT *w, string word)) //check if prefix can be combined
{
if(word == "") { //base case: all char found
return true;
} else {
for(int i = 0; i < w->alpha.size(); i++) { //Loop through all of the children of the current node
if (w->alpha[i].letter == word[0])
return containsWordHelper(w->alpha[i].next, word.substr(1));
else if (word[0] == '0') //if '0' then step over and continue searching for valid path
containsWordHelper(w->alpha[i].next, word.substr(1)); //removed return here to allow looping through all the possible paths
} //I think it is continuing through after the loop and triggering return false
}
return false; //if char is missing - meaning the exact code is not there
}
The problem is that this returns false when a '0' wildcard is used. What is going wrong here? My knowledge is limited.
I hacked on this problem for awhile and used the 'howboutthis howboutthat' approach, and found that placing the return at the end of the step over statement works.
bool Lexicon::containsWordHelper(nodeT *w, string word, int &time, int &wag, string compare) //check if prefix can be combined
{
if(word == "") { //base case: all letters found
if ((w->begin-wag) <= time && time <= (w->end+wag))
return w->isWord; // case 2: timecard check for high/low date range
else if (time == ConvertDateToEpoch(9999, 01, 01)) return w->isWord; //this is for single code lookup w/o date
} else {
for(int i = 0; i < w->alpha.size(); i++) { //Loop through all of the children of the current node
if (w->alpha[i].letter == word[0])
return containsWordHelper(w->alpha[i].next, word.substr(1), time, wag, compare);
else if (word[0] == 'ž')
if (containsWordHelper(w->alpha[i].next, word.substr(1), time, wag, compare)) return true;
}
}
return false; //if char is missing - meaning the exact code is not there
}
It seems logical that if I only one the path that ends in true to return then I should place the return after the recursion is done and then conditionally pass back only if true. It works and seems logical in retrospect, but my confidence in this is sketchy at best.
I still have the same question. What is/was going wrong?
You could test the result of the latter containsWordHelper call and return true if the result is true, else continue iterating.
Solved: place a return after an if statement containing the recursive call
bool Lexicon::containsWordHelper(nodeT *w, string word)
{
if(word == "") return w->isWord;
else {
for(int i = 0; i < w->alpha.size(); i++) {
if (w->alpha[i].letter == word[0])
return containsWordHelper(w->alpha[i].next, word.substr(1));
else if (word[0] == 'ž')
if (containsWordHelper(w->alpha[i].next, word.substr(1))) return true;
}
}
return false;
}
Related
Following is a representation of a maze that I wish to solve using recursion. S is the starting point and F is the finishing point. The numbers on top and left represent the coordinates.
I have written the code but the problem is that when the current position is 3,2 then there are 3 options for next current position: top, left and down.
If I remove the option to go leftward, then it is solved correctly and the output is "Maze not solved" because current positive never reaches F(finishing coordinate).
However, with leftward condition, I get no solution and an infinite loop is run.
Here's part of the code (only including direction==3 which means if next move will be leftward):
bool solveRecursive(char grid[][6],int siz, int curRow, int curCol, int direction,bool check)
{
while(check==0)
{
if(curRow==4 && curCol==0)
{
check = 1;
}
else if (direction == 3) // If open space in west
{
//}
if(grid[curRow][curCol-1] == '.')
{
curCol--;
check = solveRecursive(grid,siz,curRow,curCol,3,check);
}
if (grid[curRow-1][curCol] == '.')
{
curRow--;
check = solveRecursive(grid,siz,curRow,curCol, 0,check);
}
else if (grid[curRow+1][curCol] == '.')
{
curRow++;
check = solveRecursive(grid,siz,curRow, curCol, 2,check);
}
else
return 0;
}
}
return check;
}
The code is to read instructions from text file and print out graphic patterns. One is my function is not working properly. The function is to read the vectors of strings I've got from the file into structs.
Below is my output, and my second, third, and sixth graphs are wrong. It seems like the 2nd and 3rd vectors are not putting the correct row and column numbers; and the last one skipped "e" in the alphabetical order.
I tried to debug many times and still can't find the problem.
typedef struct Pattern{
int rowNum;
int colNum;
char token;
bool isTriangular;
bool isOuter;
}Pattern;
void CommandProcessing(vector<string>& , Pattern& );
int main()
{
for (int i = 0; i < command.size(); i++)
{
Pattern characters;
CommandProcessing(command[i], characters);
}
system("pause");
return 0;
}
void CommandProcessing(vector<string>& c1, Pattern& a1)
{
reverse(c1.begin(), c1.end());
string str=" ";
for (int j = 0; j < c1.size(); j++)
{
bool foundAlpha = find(c1.begin(), c1.end(), "alphabetical") != c1.end();
bool foundAll = find(c1.begin(), c1.end(), "all") != c1.end();
a1.isTriangular = find(c1.begin(), c1.end(), "triangular") != c1.end() ? true : false;
a1.isOuter = find(c1.begin(), c1.end(), "outer") != c1.end() ? true : false;
if (foundAlpha ==false && foundAll == false){
a1.token = '*';
}
//if (c1[0] == "go"){
else if (c1[j] == "rows"){
str = c1[++j];
a1.rowNum = atoi(str.c_str());
j--;
}
else if (c1[j] == "columns"){
str = c1[++j];
a1.colNum = atoi(str.c_str());
j--;
}
else if (c1[j] == "alphabetical")
a1.token = 0;
else if (c1[j] == "all"){
str = c1[--j];
a1.token = *str.c_str();
j++;
}
}
}
Before debugging (or posting) your code, you should try to make it cleaner. It contains many strange / unnecessary parts, making your code harder to understand (and resulting in the buggy behaviour you just described).
For example, you have an if in the beginning:
if (foundAlpha ==false && foundAll == false){
If there is no alpha and all command, this will be always true, for the entire length of your loop, and the other commands are all placed in else if statements. They won't be executed.
Because of this, in your second and third example, no commands will be read, except the isTriangular and isOuter flags.
Instead of a mixed structure like this, consider the following changes:
add a default constructor to your Pattern struct, initializing its members. For example if you initialize token to *, you can remove that if, and even the two bool variables required for it.
Do the parsing in one way, consistently - the easiest would be moving your triangular and outer bool to the same if structure as the others. (or if you really want to keep this find lookup, move them before the for loop - you only have to set them once!)
Do not modify your loop variable ever, it's an error magnet! Okay, there are some rare exceptions for this rule, but this is not one of them.
Instead of str = c1[++j];, and decrementing later, you could just write str = c1[j+1]
Also, are you sure you need that reverse? That makes your relative +/-1 indexing unclear. For example, the c1[j+1 is j-1 in the original command string.
About the last one: that's probably a bug in your outer printing code, which you didn't post.
I have a mini program I’m working on for class. The program is of correct syntax. Logically I cannot get the program to compute the remaining data after it completes the first else if statement that it matches.
I am subtracting numbers from each (a >= b) at each else if, the remaining value I am then assigning to a variable temp and using (temp >= c), rinse and repeat till value is zero. Each else if, will assign a char ‘A’ – ‘Z’ depending on the scenario. The problem I am having is it will meet one of the first else if’s but will not continue working the remaining else-ifs. I know this is standard of how if, else works. My question is how would I go about getting the remaining else ifs examined after the first one checks out. Is the only solution to use a switch function? Is there no way I can use if else and have each else checked/passed till my value = 0?
Just forget using else if, use a chain of if statements instead. For example:
bool isThisThree(int number, string &message)
{
if(number == 1)
message = "No, it's a one!";
if(number == 2)
message = "No, it's a two!";
if(number == 3) {
message = "Yes!";
return true;
}
if(number == 4)
message = "No, it's a four!";
if(number == 5)
message = "No, it's a five!";
return false;
}
In this example, the if statements will be examined one by one until the function hits a return statement.
Given three string sequences "abb" "ab" "a".
Now I need to find algorithm to check if a string can be parsed by above sequences .Example
string "abbabab" can be parsed by sequences "abb" "ab" and "ab"
String "abbbaaa" It cannot be parsed as we dont have "b" sequence.
I have written following code, but I feel that its not right algo.Any suggestions.
bool checkIsStringCanBeParsed(std::string S) {
std::string seqArray[6]={"abb","ab","a","abb","ab","a"};
int index=0;
int lastIndex=0;
for(int i=0;i<6;++i)
{
lastIndex =index;
for(int idx=0;idx<seqArray[i].length();++idx)
{
if(index >= S.length())
{
index =lastIndex;
break;
}
if(S[index] == seqArray[i][idx])
{
++index;
continue;
}
else
break;
}
if(index == S.length())
return true;
}
return false;
}
What you are trying to do is to build a regular expression engine that accepts sentences from the expression (abb|ab|a)*, an option is to use a non deterministic automata to represent that regular expression. Using this tool I was able to generate:
Here we have a graph with 3 states. When you want to see if a given string is accepted by your rules then it must be accepted by this graph, by accepted it means that reading the string char by char you should be able to navigate through the graph always using valid steps. When a string is parsed you should always start at state 0.
For example string "aaba" will lead us to state 0, state 1, state 1, state 2, state 1, so the string is valid because we where able to parse it completely. The string "abbb" will lead us to state 0, state 1, state 2, state 3 but there is no way to go from state 3 using another 'b' so this string is not valid.
Pseudocode to do this:
boolean accept(word, state)
{
if(word.length == 0) //either the string is empty or the parsing has ended succesfully
{
return true;
}
else
{
parsingChar = word[0] //first char of string
switch state
case 0:
if (parsingChar == 'a')
return accept(substring(word,1),1); //recursive call, we remove the first char and move to state 1
else
return false; // the first char is not an 'a' the word is not accepted
break;
case 1:
if (parsingChar == 'a')
return accept(substring(word,1),3); // move to state 3
else if (parsingChar == 'b')
return accept(substring(word,1),2); // move to state 2
else
return false; //
break;
case 2:
if (parsingChar == 'a')
return accept(substring(word,1),3); // move to state 3
else if (parsingChar == 'b')
return accept(substring(word,1),1); // move to state 1
else
return false; //
break;
case 3:
if (parsingChar == 'a')
return accept(substring(word,1),1); // move to state 1
else
return false;
break;
}
}
You should use regex. A regex for your sequences is "^((abb)|(ab)|(a))*$". The regex library will optimize it for you.
Dynamic programming should work fine. Let's say dp(i) = true if and only if it is possible to parse prefix with length i with given sequences. Initially, dp(0) = true. Then one can compute dp values for all i the following way: if dp(j) = true and substring from j+1 to i matches one of the sequences then dp(i) = true.
I'm trying to work on a string comparison check for an introductory C++ course; it's an online course and unfortunately the instructor is not very responsive. For a current lab, I need to perform a number of manipulations on string data.
Currently, I'm working on a step to check if a string has any repeated characters, and if a repetition is found, to delete the repeated characters at their present spot and move one copy of the letter to the beginning of the string. This is only to be done for the first double to be found.
I've set up a basic counter to move through the string looking for matches, checking a stored character (updated on each iteration) to the current position in the string.
I tried multiple string functions (comparing the current inputString[i] to the previous such, stored as a second string tempStore), but those always gave char conversion errors. I've tried the below instead, but this is now giving an error: "invalid conversion from 'char' to 'const char*'.
inputString is given by the user, testA and testB are defined as type char
Any ideas?
while (opComplete == false) {
if (i == 0) {
i++;
}
else if (i == inputString.size()) {
//Not Found
opComplete = true;
}
else if (i > 0) {
testA = inputString[i-1];
testB = inputString[i];
if (strcmp(testA,testB) != 0) {
i++;
}
else {
inputString.insert(0,inputString[i]);
inputString.erase(i,1);
inputString.erase(i-1,1);
opComplete = true;
}
}
}
Your problem is in this line:
inputString.insert(0,inputString[i]);
The std::string.insert() function the way you call it here has the following signature:
string& insert ( size_t pos1, const char* s );
so it expects a const char pointer. You, however, are giving it the inputString[i]. The return value of std::string.operator[] is a reference (as here), hence the error. However, by the time you reach your else, you already have the desired character in your testB variable, so you can just change the line to
inputString.insert(0, &testB);
You also can't pass normal chars into strcmp. You can use operator==, or, in your case, operator!= though.
You are using the insert method incorrectly, check its reference here for possible arguments.
while (opComplete == false)
{
if (i == 0)
i++;
else if (i == inputString.size())
opComplete = true;
else if (i > 0) {
char testA = inputString[i-1];
char testB = inputString[i];
if(testA!=testB)
i++;
else {
inputString.insert(0,&testB); //Problem Corrected here.
inputString.erase(i,1);
inputString.erase(i-1,1);
opComplete = true;
}
}
}