Changing function argument to global variable causes unexpected results - c++

I'm solving a backtracking problem. I have to construct a permutation of length n in such a way that the sum of each adjacent elements are prime. The permutation is circular, the last element is adjacent to first element. Note that all valid permutations should start with 1.
void recurse(int i, int prev, int n, vector<int> prime_ring) {
if (i == n) {
prime_ring.insert(prime_ring.begin(), 1);
if (!is_prime[prime_ring.back() + 1])
return;
for (auto data : prime_ring)
cout << data << " ";
cout << "\n";
prime_ring.clear();
return;
}
for (int next = 2; next <= n; next++) {
if (!seen[next] && is_prime[prev + next]) {
prime_ring.push_back(next);
seen[next] = true;
recurse(i + 1, next, n, prime_ring);
seen[next] = false;
prime_ring.pop_back();
}
}
}
The above code generates the wanted permutations correctly. For example for n = 4. Permutations should be
1 2 3 4
1 4 3 2
void recurse(int i, int prev, int n) {
if (i == n) {
prime_ring.insert(prime_ring.begin(), 1);
if (!is_prime[prime_ring.back() + 1])
return;
for (auto data : prime_ring)
cout << data << " ";
cout << "\n";
prime_ring.clear();
return;
}
for (int next = 2; next <= n; next++) {
if (!seen[next] && is_prime[prev + next]) {
prime_ring.push_back(next);
seen[next] = true;
recurse(i + 1, next, n);
seen[next] = false;
prime_ring.pop_back();
}
}
}
Changing prime_ring to a global vector, results in runtime error. This problem happened to me many times, I failed to realise what's wrong. I'm not aware of the difference between global vector vs function argument vector.

I'm not aware of the difference between global vector vs function argument vector.
The difference is that when you pass a vector as a parameter, the vector is copied. On the other hand when you use a global variable, there is only one `vector.
The solution here is to not use a global variable since you have a working function.

Suppose you are on the line
recurse(i + 1, next, n);
where i == n - 1
Suppose when you go into the recurse function, is_prime[prime_ring.back() + 1] is true.
Then you call prime_ring.clear();, and returns.
Afterwards, you call prime_ring.pop_back();
What happens if you try to pop_back() from an empty vector? Well, bad things can happen (namely, Undefined Behaviour)

Related

Iterative / Recursion

I have written the code for how to find the permutations for a given string using a for loop. I followed my professor's pseudocode, but am not sure how to convert it so that it is recursive. (no for, goto, while, STL algorithms).
void perms(string prefix, string rest)
{
// Followed Format of Pseudocode that Professor gave us
// If nothing remains in the rest string cout what we have for prefix
if (rest == "")
{
cout << prefix << endl;
}
else
{
for (int i = 0; i < rest.length(); i++)
{
string prefix2 = prefix + rest[i];
string rest2 = rest.substr(0, i) + rest.substr(i + 1);
perms(prefix2, rest2);
}
}
}
The code works well, just need help with turning it to recursion.
To hoist the loop into the recursion, you have to turn the iteration variable i into a parameter:
Step 1:
void printPermutations(string prefix, string rest, int i = 0)
Step 2:
void printPermutations(string prefix, string rest, int i = 0)
{
// Followed Format of Pseudocode that Professor gave us
// If nothing remains in the rest string cout what we have for prefix
if (rest == "")
{
cout << prefix << endl;
}
else if (i < rest.length())
{
// original loop body
string prefix2 = prefix + rest[i];
string rest2 = rest.substr(0, i) + rest.substr(i + 1);
// true original recursion with different prefix and tail.
printPermutations(prefix2, rest2);
// loop continuation via tail recursion: original prefix, next i.
printPermutations(prefix, rest, i + 1);
}
}
It's almost mechanical transformation. Firstly, the initialization of i to 0 has moved into the argument list where we do that via defaulting (we could also have callers explicitly pass zero, when necessary). The for loop header of the loop has been gutted, replaced just with the loop guard condition, which is transformed to an if conditional. And then the continuation of the loop is done just by a tail call where we pass i + 1, which becomes the next value of i.
It might help to imagine this intermediate version, which is still iterative:
void printPermutations(string prefix, string rest)
{
int i = 0;
topOfFunction:
// Followed Format of Pseudocode that Professor gave us
// If nothing remains in the rest string cout what we have for prefix
if (rest == "")
{
cout << prefix << endl;
}
else if (i < rest.length())
{
// original loop body
string prefix2 = prefix + rest[i];
string rest2 = rest.substr(0, i) + rest.substr(i + 1);
// true original recursion with different prefix and tail.
printPermutations(prefix2, rest2);
// loop continuation via tail recursion: original prefix, next i.
i = i + 1;
goto topOfFunction;
}
}
Note that though the rest == "" check is included in the loop, we know that stays false because we never modify rest.
Every loop can be turned into recursion:
void test() {
int functionVar = 10;
int sum = 0;
for (int i=0, int j=2; i<10; i = i - 1, j = j + 2) {
sum = sum + someFun(i, functionVar);
}
// Do something with sum
cout << sum << endl;
}
Can easily be rewritten like this:
int forReplacement(int i, int j, int sum, functionVar) {
if (i < 2) {
return forReplacement(i - 1, j + 2, sum + someFun(i, functionVar), functionVar);
}
return sum;
}
void test() {
int functionVar = 10;
int sum = forReplacemenrt(0, 0, 0, functionVar);
// Do something with sum
cout << sum << endl;
}
You could make forReplacement a lambda and point reference it in it's closure to be able to recur and then functionVar and sum could be closure variables.

Recursive function that returns a sum of all elements in a vector

I am confused on how to get this function to add the last element in the vector. I cannot modify the functions parameters.
long vectorSum(const std::vector<int>& data, unsigned int position)
{
if (position == data.size()-1)
{
return 0;
}
else
{
return (vectorSum(data, position+1) + data[position]);
}
}
int main()
{
//vectorSum test
std::vector<int> data = { 1,2,3,4,5};
unsigned int pos = 0;
std::cout << "expected: 15, " << "actual: " << vectorSum(data, pos) << std::endl;
}
when you stop at data.size() -1 you are returning 0 for vectorSum(data, data.size()-1) without counting the value of the last entry
long vectorSum(const std::vector<int>& data, unsigned int position)
{
if (position == data.size()) // You were stopping early
{
return 0;
}
else
{
return (vectorSum(data, position+1) + data[position]);
}
}
int main()
{
//vectorSum test
std::vector<int> data = { 1,2,3,4,5};
unsigned int pos = 0;
std::cout << "expected: 15, " << "actual: " << vectorSum(data, pos) << std::endl;
}
When you're looking at the last element, you have this condition:
if (position == data.size()-1)
At this point, position is 4, and data.size() is 5. So the condition matches and the recursion ends.
You need to change the == to >, or drop the -1
There are always two parts to a recursive function: a stop condition and a recursion. A simple stop condition here is: when there are no elements in the vector, the sum is 0. The recursion is: the sum of the elements of a non-empty vector is the value of its first element plus the sum of the remaining elements. In code, the stop condition looks like this:
if (position == data.size())
return 0;
In code, the recursion looks like this:
else
return data[position] + vectorSum(data, position + 1);
A slightly more sophisticated stop condition would be: when there is exactly one element in the vector, the sum is the value of that element. In code:
if ( position == data.size() - 1)
return data[position];
Compared to the first one, this has one fewer levels of recursion. But it doesn't work for empty vectors. So pick your poison.
The problem with the original code is that its stop condition isn't implemented correctly. It inter-mixes these two stop conditions.

c++ : dynamic number of nested for loops (without recursion)

I'm writing a code segment that iterates through every permutation of n digits. So for example, if n = 3, I would want to iterate through each of the following elements:
0, 0, 0
...
0, 1, 0
...
1, 0, 0
...
2, 3, 4
...
9, 9, 9
This is very easy to code using nested for loops:
for(digit1 0 to 9)
for(digit2 0 to 9)
for(digit3 0 to 9)
But I want to generalize this for n digits. If for example n = 10, I now need 10 nested for loops.
I've thought about this and realized that the problem can be solved using recursion (depth first search through a tree, with each node having 10 children, 0 to 10, and stopping at depth n). But I'm aiming for high performance so I don't want to use recursion due to the overhead. What other alternatives do I have?
If you want to simulate nested loops with a single one without using recursion, you can do so by maintaining a set of states (or slots) for each looping variable, which can be easily done with an array. Looping then turns into a simple matter of "adding 1" to that array, performing the carry operations as needed. If your nesting depth is n, and your maximum boundary for each loop is b, then the runtime of this is O(b^n), because the carry operations will only cost you at most O(b^n) (I'll skip the algebra here).
Here is the working C++ code (updated to integrate Drew's comment):
void IterativeNestedLoop(int depth, int max)
{
// Initialize the slots to hold the current iteration value for each depth
int* slots = (int*)alloca(sizeof(int) * depth);
for (int i = 0; i < depth; i++)
{
slots[i] = 0;
}
int index = 0;
while (true)
{
// TODO: Your inner loop code goes here. You can inspect the values in slots
// Increment
slots[0]++;
// Carry
while (slots[index] == max)
{
// Overflow, we're done
if (index == depth - 1)
{
return;
}
slots[index++] = 0;
slots[index]++;
}
index = 0;
}
}
In genreral case if you like to replace recursion to flat code you should use the stack (LIFO). So if you have recursive algorithm:
void print(std::string str, int depth)
{
if (depth == n) {
std::cout << str << std::endl;
return;
}
for (int i = 0; i < 10; ++i) {
char val[2] = { i + '0', 0 };
print(str + val + ", ", depth+1);
}
}
You can transform it to LIFO-based with saving local variables (str and i in this case):
struct StackItem {
StackItem(const std::string& ss, unsigned ii)
: str(ss), i(ii)
{}
std::string str;
int i;
};
void print_norec()
{
std::list< StackItem > stack;
stack.push_back(StackItem("", 0));
while (!stack.empty()) {
StackItem& current = stack.back();
if (stack.size() == n+1) {
std::cout << current.str << std::endl;
stack.pop_back(); // return from "recursive" function
continue;
}
if (current.i < 10) {
char val[2] = { current.i + '0', 0 };
// call "recursive" function
stack.push_back(StackItem(current.str + val + ", ", 0));
current.i++;
} else {
stack.pop_back(); // return from "recursive" function
}
}
}
If you want the permutation for all the digits for a specific length;as you have shown example of 3 digits. Instead of running 3 nested loops, run a single loop of 10^3 which will give you all the permutations.
Split the number obtained into digits in each iteration if you want to use it for indexing.
Thus you will be needing just one loop rather than nested loops.

Recursive function that takes the sum of odd integers

The program runs but it also spews out some other stuff and I am not too sure why. The very first output is correct but from there I am not sure what happens. Here is my code:
#include <iostream>
using namespace std;
const int MAX = 10;
int sum(int arrayNum[], int n)
{
int total = 0;
if (n <= 0)
return 0;
else
for(int i = 0; i < MAX; i ++)
{
if(arrayNum[i] % 2 != 0)
total += arrayNum[i];
}
cout << "Sum of odd integers in the array: " << total << endl;
return arrayNum[0] + sum(arrayNum+1,n-1);
}
int main()
{
int x[MAX] = {13,14,8,7,45,89,22,18,6,10};
sum(x,MAX);
system("pause");
return 0;
}
The term recursion means (in the simplest variation) solving a problem by reducing it to a simpler version of the same problem until becomes trivial. In your example...
To compute the num of the odd values in an array of n elements we have these cases:
the array is empty: the result is trivially 0
the first element is even: the result will be the sum of odd elements of the rest of the array
the first element is odd: the result will be this element added to the sum of odd elements of the rest of the array
In this problem the trivial case is computing the result for an empty array and the simpler version of the problem is working on a smaller array. It is important to understand that the simpler version must be "closer" to a trivial case for recursion to work.
Once the algorithm is clear translation to code is simple:
// Returns the sums of all odd numbers in
// the sequence of n elements pointed by p
int oddSum(int *p, int n) {
if (n == 0) {
// case 1
return 0;
} else if (p[0] % 2 == 0) {
// case 2
return oddSum(p + 1, n - 1);
} else {
// case 3
return p[0] + oddSum(p + 1, n - 1);
}
}
Recursion is a powerful tool to know and you should try to understand this example until it's 100% clear how it works. Try starting rewriting it from scratch (I'm not saying you should memorize it, just try rewriting it once you read and you think you understood the solution) and then try to solve small variations of this problem.
No amount of reading can compensate for writing code.
You are passing updated n to recursive function as argument but not using it inside.
change MAX to n in this statement
for(int i = 0; i < n; i ++)
so this doesnt really answer your question but it should help.
So, your code is not really recursive. If we run through your function
int total = 0; //Start a tally, good.
if (n <= 0)
return 0; //Check that we are not violating the array, good.
else
for(int i = 0; i < MAX; i ++)
{
if(arrayNum[i] % 2 != 0) //THIS PART IS WIERD
total += arrayNum[i];
}
And the reason it is wierd is because you are solving the problem right there. That for loop will run through the list and add all the odd numbers up anyway.
What you are doing by recursing could be to do this:
What is the sum of odd numbers in:
13,14,8,7,45,89,22,18,6,10
+
14,8,7,45,89,22,18,6
+
8,7,45,89,22,18
+
7,45,89,22 ... etc
And if so then you only need to change:
for(int i = 0; i < MAX; i ++)
to
for(int i = 0; i < n; i ++)
But otherwise you really need to rethink your approach to this problem.
It's not recursion if you use a loop.
It's also generally a good idea to separate computation and output.
int sum(int arrayNum[], int n)
{
if (n <= 0) // Base case: the sum of an empty array is 0.
return 0;
// Recursive case: If the first number is odd, add it to the sum of the rest of the array.
// Otherwise just return the sum of the rest of the array.
if(arrayNum[0] % 2 != 0)
return arrayNum[0] + sum(arrayNum + 1, n - 1);
else
return sum(arrayNum + 1, n - 1);
}
int main()
{
int x[MAX] = {13,14,8,7,45,89,22,18,6,10};
cout << sum(x,MAX);
}

Recursive Function Scanning String to Add ASCII

So I'm trying to figure out how to do this:
Write a recursive function that will sum all of the char's within a C String.
I'm a little rusty in doing this normally, but I finally got it to work with a normal for loop:
int countstr(string s)
{
int sum = 0;
if(s.length() == 0)
{
exit(0);
}
for (unsigned int i = 0; i < s.size(); i++)
{
sum += s[i];
}
return sum;
}
I can then go inside main and do this:
int main ()
{
cout << "This word adds up to " << countstr("HELLO") << " in ASCII " << endl;
}
and everything works as it should, counting and adding up the characters in the string via their ASCII numbers.
The problem I'm having is trying to figure out how this is typed up so it works recursively. I know I need to forgo the for loop in lieu of calling up the function itself, but I don't know what to use instead of the sum += s[i]; that I have going in my for loop. I've been looking around in the C string library, but I don't see anything that can replace the [i] that the for loop calls up. Does anyone know what I should be using to do this? I'm not looking for an answer in code, just need help in what I should be using to make this happen.
This is one of many ways to do it.
int reccountstr(string s, int i){
if(s.size() == i)
return (0 + s[i]);
else
return reccountstr(s, i + 1) + s[i];
}
And then in main you just call it with a zero initial argument.
cout << "This word adds up to " << reccountstr("HELLO", 0) << " in ASCII " << endl;
Skeleton could be like this:
int countlen(const char * str)
{
if (condition)
return 0;
else
return *str + countlen(str + 1);
}
The rest is up to you :)
int countString(char sample[], int i)
{
if(sample[i] == 0)
return 0;
else
return(1 + countString(sample, i+1));
}
This could be one solution, where if the current character read is not null (0, or '\0') it will return 1 + countString(sample, i + 1) where i is the current character index to be read.
Once it reaches null it returns 0. So for a character length of three, it will do 1 + 1 + 1 + 0. You can call the function with printf("%d\n", countString(yourStringName, 0)).
So your base case here is character[index] == empty
Your inductive case is 1 + function(stringName, index + 1), roughly speaking.
Also, this is a little outside the scope of your question, but you can also make this more efficient by avoiding constantly building up the stack. A way to do this is to create another variable inside the function that continuously accumulates the total count. For more info on this see this link on tail recursion:
http://c2.com/cgi/wiki?TailRecursion
More memory conservative version:
int countString(char sample[], int i, int total)
{
if(sample[i] == 0)
return total;
else
return countString(sample, i+1, ++total);
}
You can call this with printf("%d\n", countString(sample, 0, 0));