Recursive Function Scanning String to Add ASCII - c++

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));

Related

Changing function argument to global variable causes unexpected results

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)

why am I getiing 0 as a result,I want the return value as the result?

I want the result to be the returned value from the mystery function,but the result is always 0 .but I want the program to return a value that's collected from the mystery function
#include <iostream>
using namespace std;
int Mystery(int n)
{
// int k;
if (n <= 1)
{
return 0;
}
else
{
int k = n;
for (int i = 1; i <= n; i++)
{
k = k + 5;
}
cout << ((k * (n / 2)) + (8 * (n / 4)));
cout << "\n ";
return ((k * Mystery(n / 2)) + (8 * Mystery(n / 4)));
}
}
int main(void)
{
int i, n;
cout << "Enter n:"; //array size
cin >> n;
int result = Mystery(n);
cout << "The result is " << result;
return 0;
}
Let's desk check what happens when you call Mystery(2). The final return value is:
((k* Mystery(n/2)) + (8* Mystery(n/4)))
We know that n == 2 so let's substitute that:
((k* Mystery(1)) + (8* Mystery(0 /* by integer division of 2/4 */)))
This will call the function recursively twice with the respective arguments 1 and 0. But we know that the terminating case n <= 1 returns 0, so we can substitute that:
((k* 0) + (8* 0))
Anything multiplied by zero is zero, so this reduces to 0 + 0 which is also zero. It doesn't even matter what k is.
Quite simply, the terminating case for this recursion mandates that the result is always zero.
In the terminating case the return value is zero.
In the recursive case, the recursive call result is multiplied with another value to produce the return value.
Therefore, the result is always going to be zero for any n.
I'm not sure exactly how this function is supposed to work as you have not explained that, but changing the terminating case to return 1; may solve the problem.
I don't expect which result you want, but I think you can get write result when you correct conditions like
if (n == 0)
return 0;
if (n == 1)
return 1;
I hope it returns the right result.

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.

Not able to generate correct output in recursive function?

I'm trying to write a function that detects the number the negative integers in a stack recursively. Currently the snippet below is what I have, however it is not giving the correct answer so far. I tested with a stack of 11 elements with 7 negatives and got the output given below. There is definitely something wrong with the loop structure but I have not been able to pinpoint and fix it yet. Any help will be appreciated!
12356657235681623569772357137235729723574562357617235777623579372358096
My function below:
size_t r_func(stack<int> st1)
{
if(st1.size() == 0) return 0;
int r = st1.top();
st1.pop();
cout << (r<0)+r_func(st1);
}
size_t r_func(stack<int> st1)
{
if(st1.size() == 0) return 0;
int r = st1.top();
st1.pop();
cout << (r<0)+r_func(st1);
}
r_func is supposed to return a size_t, but if st1.size() is not zero then it won't return anything. The compiler should've given you a warning about this!
To correct this, add a line that returns the number of negative numbers in your stack:
...
st1.pop();
const size_t neg_count = (r < 0) + r_func(st1);
cout << neg_count;
return neg_count;
}
Edit: To write this tail-recursively, it's necessary to keep track of the size in an accumulator (here it's called neg_accum):
size_t r_func(stack<int> st1, size_t neg_accum = 0)
{
if (st1.size() == 0) {
cout << neg_accum;
return neg_accum;
}
int r = st1.top();
st1.pop();
return r_func(st1, (r < 0) + neg_accum);
}
As Rufflewind said, you should replace 'cout <<' with 'return' and call your function in this way: 'cout << r_func(st1);'

Print accumulated sums in C++ in a recursive function

So I have this function and these global variables.
int recurs=0;
std::string sign="";
void count2(int k, std::vector<int> d, int total, int temp, bool flag, unsigned short int pos){
std::string mas="+";
std::string menos="-";
if(pos==(d.size())){
total+=temp;
if(total==k){
result++;
std::cout << sign << "=" << k<<std::endl;
str="";
}
recurs++;
return;
}
//Sum sign.
sign=sign.substr(0,sign.size()-recurs*2);
sign.append(mas+=std::to_string(d[pos]));
count2(k,d,total+temp,+d[pos],true,pos+1);
//Rest sign
sign=sign.substr(0,sign.size()-recurs*2);
sign.append(menos+=std::to_string(d[pos]));
count2(k,d,total+temp,-d[pos],false,pos+1);
//Append digit
if(flag==true)
count2(k,d,total,10*temp-d[pos],true,pos+1);
else
count2(k,d,total,+10*temp+d[pos],false,pos+1);
}
The function is called like this:
count2(6,{1,2,3,3,3},0,0,true,0);
What it does: Given a vector v, it makes combinations of sums and substractions and numbers and everytime that this combination equals the first parameter, a global variable result is increased. For example, count2(6,{1,2,3,3,3},0,0,true,0); would make result be 5. Since there is 5 ways to sum/sub 6 with those numbers, e.g.: 1+2+3+3-3 1+2-3+3+3 and some others. It works perfectly. Also, the variable string str is not used.
What is wrong? Nothing, but I'd like to see which these combinations are. I'd like the function to print thinks like:
1+2+3+3-3
1+2-3+3+3
-1-2+3+3+3
1+2+3-3+3
What is the question? I'd like to know how to correctly print the operatins that make total be equal to k.
If you were to run this code in ideone, it would print: YES, This is my actual outcome. But is not correct since there's no sum such as +3 or +3+3+3+3+3+3+....
+1+2+3+3-3=6
+3=6
+3-3+3-3-3+3+3=6
+3-3+3-3-3+3+3-3-3+3-3+3-3+3+3-3-3+3-3+3-3-2+3+3+3-3-3+3-3+3-3-3+3+3-3-3+3-3+3-3+3+3-3-3+3-3+3-3+3+3+3-3-3+3-3+3-3-3+3+3-3-3+3-3+3-3+3+3-3-3+3-3+3-3-1+2+3+3+3-3-3+3-3+3-3-3+3+3-3-3+3-3+3-3+3+3-3-3+3-3+3-3-2+3+3+3=6
+3-3+3-3-3+3+3-3-3+3-3+3-3+3+3-3-3+3-3+3-3-2+3+3+3-3-3+3-3+3-3-3+3+3-3-3+3-3+3-3+3+3-3-3+3-3+3-3+3+3+3-3-3+3-3+3-3-3+3+3-3-3+3-3+3-3+3+3-3-3+3-3+3-3-1+2+3+3+3-3-3+3-3+3-3-3+3+3-3-3+3-3+3-3+3+3-3-3+3-3+3-3-2+3+3+3-3-3+3-3+3-3-3+3+3-3-3+3-3+3-3+3+3-3-3+3-3+3-3+3+3+3-3-3+3-3+3-3-3+3+3-3-3+3-3+3-3+3+3-3-3+3-3+3-3+2+3+3+3-3-3+3-3+3-3-3+3+3-3-3+3-3+3-3+3+3-3-3+3-3+3-3-2+3+3+3=6
The correct outcome could look like:
1+2+3+3-3
1+2+3-3+3
1+2-3+3+3
-1-2+3+3+3
Question answered!
If you don't mind me changing the function signature a little bit, may I suggest the following?
int recurs = 0;
void count2(int k, std::vector<int> d, int total = 0, std::string temp = "", unsigned short pos = 0)
{
if(pos == d.size())
{
//test total number
if(total == k)
{
std::cout << temp <<"=" << k << std::endl;
recurs++;
}
}
else
{
//test each operator on next number in sequence
count2(k, d, total + d[pos], temp + ((pos) ? "+":"") + std::to_string(d[pos]), pos + 1);
count2(k, d, total - d[pos], temp + "-" + std::to_string(d[pos]), pos + 1);
}
}
The conditional operator will remove the '+' sign from the beginning. Default values make the function easier to call from main or wherever. By sending temp as a string, it is easier to keep track of the final equation, as well as removing it as a global variable. It also removes the need for your bool flag variable. Last, total is updated in the function call to remove clutter from the function body.
So finally count2 looks like this:
void count2(int k, std::vector<int> d, int total, int temp, bool flag, unsigned short int pos, std::vector<std::string> s){
//std::cout << temp << " ";
if(pos==(d.size())){
total+=temp;
if(total==k){
result++;
for(unsigned short int i=0;i<d.size();i++){
std::cout << s[i] << d[i];
}
std::cout << "=" << k <<"\n";
}
return;
}
s[pos]="+";
count2(k,d,total+temp,+d[pos],true,pos+1,s);
//put a - sign in pos
s[pos]="-";
count2(k,d,total+temp,-d[pos],false,pos+1,s);
if(pos==0) return;
//Append digit
if(flag==true){
s[pos]="";
//std::cout << "<0 " << 10*temp-d[pos] << " ";
count2(k,d,total,(10*temp-d[pos]),true,pos+1,s);
}
else{
s[pos]="";
//std::cout << ">0" << 10*temp+d[pos] << " ";
count2(k,d,total,10*temp+d[pos],false,pos+1,s);
}
}
You can see instead of using a string variable, I'm using a string vector, which makes it suitable for the recursion call.
Give it a try on ideone.com