I've been trying to get a better understanding of recursive functions, and I was working on a problem trying to figure out why it wasn't working properly.
I want it to go through the array, and when it finds a 0, to return true.
But the function stills return true when there's no zero.
Here is my code:
bool containZero(int randomArray[], int length)
{
if(randomArray[length] == 0)
return true;
else
{
return containZero(randomArray, length - 1);
}
}
Your algorithm is not handling the possibility that the array may not actually contain a zero. You need to stop iterating when the end of the array is reached.
You are also accessing the array out of bounds from the very 1st iteration, and also if no zero is found.
Not only that, but there is no branch of your recursion logic that ever returns false. Your return statements are always returning true.
Try this instead:
// this searches backwards...
bool containZero(int randomArray[], int length)
{
if (length <= 0)
return false;
--length;
if (randomArray[length] == 0)
return true;
return containZero(randomArray, length);
}
Online Demo
Alternatively:
// this searches forwards...
bool containZero(int randomArray[], int length)
{
if (length <= 0)
return false;
if (randomArray[0] == 0)
return true;
return containZero(randomArray+1, length-1);
}
Online Demo
Related
I'm trying to create a program for an assignment that will add and remove strings from a vector of strings, but first I need to create a function that will find whether or not the string already exists in the vector.
I've already tried to use a loop to search through the vector to find a specific desired string at each index. I tried adding a break; to exit if the string was found. I don't know if the function is supposed to be void or boolean.
bool FindString(int vctrSize, vector<string> restaurantVctr, string targetRestnt) {
int i;
for (i = 0; i < vctrSize; ++i) {
if (restaurantVctr.at(i) == targetRestnt) {
return true;
break;
}
else {
return false;
}
}
}
I expect the output to be true if the string was found, else it would obviously be false.
Edit: I forgot to mention that I also received the warning: "not all control paths return a value"
You should use std algorithms whenever possible:
auto result = std::find(restaurantVctr.begin(), restaurantVctr.end(), targetRestnt);
return result != restaurantVctr.end();
That is exactly what std::find is for.
While I recommend using std::find as others have recommended, if you're curious what is wrong with your code, the problem is your else:
for (i = 0; i < vctrSize; ++i) {
if (restaurantVctr.at(i) == targetRestnt) {
return true;
break;
}
else {
return false;
}
}
If the first item in your vector is not equal to targetRestnt, then your function returns--that is, it ends execution.
You only want to return false if it's not in the whole list--that is, you want the whole loop to execute:
for (i = 0; i < vctrSize; ++i) {
if (restaurantVctr.at(i) == targetRestnt) {
return true;
// Also, you don't need a break here: you can remove it completely
// For now, I just commented it out
// break;
}
}
// We didn't find it:
return false;
I'm a little confused here. Let's look at the following code:
bool testing(int i) {
if((i%2)==0) {
return true;
} else {
--i;
testing(i);
}
return false;
}
When I do testing(5), I was expecting the function to return true because at some point, 5 will become 4, so 4 % 2 == 0, so the function will return true but it just wasn't the case. What's wrong?
You should return testing(i); instead of just testing(i);
The idea of recursion is when a function calls itself, directly or indirectly.
The function in your code will become recursive if it is modified to:
bool testing(int i){
// test if even, if so return true
if((i % 2) == 0){
return true;
// otherwise decrement and test again
}else{
// at this point the function calls itself with decremented argument
return testing(--i);
}
// I doubt that this case will be ever returned
// more likely your function will return "true" or run "forever" decrementing
return false;
}
To avoid infinite cycles you need a base case, termination condition that produces result without recursion. For example if i becomes very small or negative you return false.
bool testing(int i){
// base case
if(i < 0) return false;
// rest of the function
if((i % 2) == 0){
return true;
}else{
return testing(--i);
}
}
Making it a bit more concise, you finally have three cases:
bool testing(int i){
// base case
if(i < 0) return false;
// test if even
if((i % 2) == 0) return true;
// recursion step
return testing(--i);
}
For further reading, check this
You don't bubble up the final return value; you need to use return on the recursive call. Additionally, you can simplify the pre-decrement:
return testing(--i);
Because of you only call testing(i) function. That's why it's not call recursively.
you should write return testing(i)
it returns false because its return value is overridden by the last statement of "return false".
Have no idea why this problem is so hard for me. Iteratively, this is cake but as soon as the stack unwinds it destroys my entire function.
It finds the needle correctly and gives the function a value of true if it finds it. However, it keeps reverting back to false as soon as the call stack is unwound. Does anyone know how to remedy this or what I'm doing wrong with my code?
Here is what I have so far...
bool mySubStr(char * needle, char * haystack)
{
int needleLength = strlen(needle);
int haystackLength = strlen(haystack);
bool found = false;
if(needleLength < haystackLength)
{
if(strncmp(haystack, needle, needleLength) == 0)
{
found = true;
}
else
{
mySubStr(needle, haystack + 1);
}
}
return found;
}
You need to return the result of the recursive call to mySubStr(..):
bool mySubStr(char * needle, char * haystack)
{
int needleLength = strlen(needle);
int haystackLength = strlen(haystack);
if(needleLength > haystackLength)
return false;
if(strncmp(haystack, needle, needleLength) == 0)
{
return true;
}
return mySubStr(needle, haystack + 1);
}
In your implementation, you were calling the function recursively but were discarding the result:
else
{
mySubStr(needle, haystack + 1);
}
}
return found;
So in effect, unless the needle happened to be right at the beginning, your function would always return false.
my knowledge is limited, writing in C++ for 2 months
In this function string code is recursively decrements chars until the base case "" is found. I want to prune some paths before the base case is found, and for some string code a path to the base case will not be found. For the prune I want to compare an attribute in the path with parameter int time. This searches a trie made of 'nodeT'
struct charT {
char letter;
nodeT *next;
};
struct nodeT {
bool isOperation;
bool isCode;
int time;
Vector<charT> alpha;
};
nodeT *root
usage:
string code = "12345";
int time = convertToEpoch(20120815); //my epoch function
containsCode(code, time)
bool containsCode(string code, int time)
{
if(root == NULL) return false;
else return containsCodeHelper(root, code, time);
}
bool containsCodeHelper(nodeT *w, string code, int time)
{
if(code == "") //base case: all char found
return w->isCode;
else {
if (w->isOperation && w->time != time) return false; //case 2: time check OK <- at a midpoint in the path
for(int i = 0; i < w->alpha.size(); i++) { //Loop through the leaf
if (w->alpha[i].letter == code[0]) //case 3: leaf exists
return containsCodeHelper(w->alpha[i].next, code.substr(1), time);
}
}
return false; //if no path
}
This function worked well before adding the time check prune, it now loops, returns false if outside time but then starts again with the candidate string code from char location 0.
Questions: 1) Is a nested return false kicking the recursion back to the next call for loop, 2) should the time prune be placed in the for loop with a logical return false or return 'path', 3) is this more fundamentally messed-up and I need to learn a C++ concept <- please explain if yes.
Also, the posted function is a simplified version of the actual function - there is a modifier to time and a 'step over' path that I left out. In past question I found that these 'addons' distract from the question.
after some reworking it now functions fine - possibly it always did; I changed to read attribute return w->isCode to return true, that seemed to be the biggest issue - I will debug the trie constructor and see if it is setting the attribute at the end of each path.
boolcontainsCodeHelper(nodeT *w, string code, int time)
{
if(code == "") //base case: all char found
return true;
else {
if ( w->isOperation && (!((w->begin-wag) <= time && time <= (w->end+wag) ) && time != 9999 ) )
return false; //case 2: time
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 containsCodeHelper(w->alpha[i].next, word.substr(1), time, wag);
else if (word[0] == 'ΕΎ') //step over '0' all subnodes
if (containsCodeHelper(w->alpha[i].next, word.substr(1), time, wag))
return true;
}
}
}
return false; //if char is missing - meaning the exact code is not there - terminates garbage subnode paths
}
I don't see any difference between having return false; at the end and leaving it out. Also still confused as why the special case needs if( bool fn()) return true; rather than just return ( bool fn()); i found that solution through trial and error with help from another stack overflow thread
This is one of the solution of getting true or false from given set and target value
bool subsetSumExists(Set<int> & set, int target) {
if (set.isEmpty()) {
return target == 0;
} else {
int element = set.first();
Set<int> rest = set - element;
return subsetSumExists(rest, target)
|| (subsetSumExists(rest, target- element));
}
}
However, this solution will return true or false value only. How is it possible to get the element that involve in the subset(set that add together will equal to target) as well?
Do I have to use dynamic programming? Coz as i know.. recursion is building up stack actually and after the function return the value, the value inside the frame will be discarded as well.
So, is it possible to get the elements that add up equal to the target value.
Is passing an object a solution of the problem?
Thank you
First of all you can optimize your program a little bit - check if target is 0 and if it is always return true. Now what you need is to have somewhere to store the elements that you have already used. I will show you a way to do that with a global "stack"(vector in fact so that you can iterate over it), because then the code will be easier to understand, but you can also pass it by reference to the function or avoid making it global in some other way.
By the way the stl container is called set not Set.
vector<int> used;
bool subsetSumExists(Set<int> & set, int target) {
if (target == 0) {
cout << "One possible sum is:\n";
for (int i = 0; i < used.size(); ++i) {
cout << used[i] << endl;
}
return true;
} else if(set.empty()) {
return false;
}else {
int element = set.first();
Set<int> rest = set - element;
used.push_back(element);
if (subsetSumExists(rest, target- element)) {
return true;
} else {
used.pop_back();
}
return subsetSumExists(rest, target);
}
}
Hope this helps.