My recursive function written in c++ doesn't work - c++

I wanted to make a recursive function for the multiplication of the elements from an array
If my array has 1 element and v[1] is 1 ,the program wil show me 4703488
My question is why?
#include<iostream>
using namespace std;
int prod(int n,int v[100])
{
if(n)
{
return prod(--n,v)*v[n];
}
return 1;
}
int main()
{
int v[100],n,i=1;
cout<<"n=";
cin>>n;
for(i=1;i<=n;i++)
cin>>v[i];
cout<<prod(n,v);
return 0;
}

The culprit is the line return prod(--n,v)*v[n];. When you call --n as the function parameter, you don't know which value of n will be used in the v[n] part. This causes undefined behaviour. Since the value at 0 in your array is a garbage value, it might be using that value instead of using v[1] as you planned.
The correct way to write it would be return prod(n-1, v)*v[n]. To address the OP's query, a detailed explanation is shown below:
int prod(int n,int v[100]) // n has value 1 right now, when called
{
if(n) // since n has value 1, boolean condition is satisfied and control //flow goes inside the loop
{ // inside the loop part is being executed now
return prod(--n,v)*v[n]; // the value of n is decremented with --n. So n is now 0 (or could be 1). The value in v[n] is undefined, and it may be or 1. Garbage value at 0. Hence, output has garbage value
}
return 1;
}

It does not work properly because
return prod(--n,v)*v[n];
is undefined behaviour. What value of n is used for v[n]? The one received on the function call or the value of --n?
It seems that in your case v[n] uses the value of n after the decrementation (and it uses v[0] that is not initialized). But it could be the other way around (get v[n] before --n).
You can fix it this way:
return prod(n-1,v)*v[n];

this is not well defined:
return prod(--n,v)*v[n];
the reason is, the side-effect in --n is unsequenced with respect to the read of n in v[n]

I would write the function the following way
long long int prod( const int a[], size_t n )
{
if ( n == 0 ) return 0;
else return a[n-1] * ( n > 1 ? prod( a, n - 1 ) : 1 );
}
As for your code then this statement
return prod(--n,v)*v[n];
has unspecified order of evaluation of operands of operator *.

Related

Is there a way to find the INDEX of the minimum value in an array using a recursive function? C++

I need to find the Index of the minimum number in an array using a recursive function in c++ the function can only get 2 parameters: the pointer to the array and the size of it.
int smallest(int arr[], int num);
I managed to do this but with a helper variable that is static and declared outside the function here is what I got:
static int flag = 0;
int smallest(int* arr, int num) {
if (flag == num - 1)
return flag;
if (arr[num - 1] > arr[flag]) {
return smallest(arr, num - 1);
} else {
flag++;
return smallest(arr, num);
}
}
Now my question is can I do this without the static variable or any other variable other than the num? here is what I got so far:
int smallest(int arr[], int num) {
if (arr != &arr[num - 1])
if (*arr < arr[num - 1])
smallest(arr, num - 1);
else
smallest(arr + 1, num);
return num - 1;
}
It doesn't return the index of the minimum value but it does get to its adress, the function ends when the array pointer address is the same as the address of the minimum value. how can I get it to return the index?
I'm a student and I'm pretty new to C++ I appreciate the help! thanks!
===
edit:
this is originally from a homework assignment but the constraint to not use external help variables or functions is mine! and I'm curious to know if its even possible.
Because this is obviously homework, I'm not going to reveal the ACTUAL answer in entirety, but I'll give some (hopefully) good advice.
With recursion, think first of what your end condition is. That should be an array of 1 element. You return the index 0 in that case because of the array you have, it's the only element, so return the index of it.
if(num == 1)
{
return 0;
}
So then how is that useful to you? Compare it to exactly one other element. That's how you break this down. Your array turns into "one element and MANY" or "It's just one element." If it's just one, return the only value. If it's many, call yourself recursively from the second element (index 1) onward:
int restOfArraySmallest = smallest(arr+1, num-1) + 1;
You need the +1 because you've offset where it starts from. But you know the value in restOfArraySmallest is the index into YOUR arr of the smallest value of everything except the first element. Because your recursive calls don't include the first element, just the rest.
Hopefully that's enough to get you the rest of the way.
Edit: Because the OP has responded and said it wasn't essential to their homework assignment, here's the entire function:
// Recursively finds the index of the smallest element of the passed-in array
int smallest(int* arr, int num)
{
if(num <= 1)
{
return 0; // If we're in the last element, the smallest is the only element
}
// More than one element, so find the least element in all the elements
// past the first element of the array
// Note: the index returned is offset from our current view of the array,
// so add +1 to any returned result so we can index directly from it
int restOfArraySmallest = smallest(arr+1, num-1) + 1;
// Compare the first element in the array to the smallest of the entire rest
// of the array:
if(arr[0] < arr[restOfArraySmallest])
{
// The first element is smaller, it's the smallest, so return that index
return 0;
}
else
{
// The element already found is smaller, so return that index. It's already
// correctly offset
return restOfArraySmallest;
}
}
And that's it. If there's duplicate entries for smallest, it will favor the LAST one.
The trick with recursion is to NOT keep external variables. What you pass as the arguments and RETURN BACK are all the information you have. For some algorithms, it's enough.
Note, if you use recursive functions with datasets big enough, you will eventually get a Stack Overflow. Not the website, the crash type. This algorithm is pretty light in that only one extra variable and the two arguments themselves get allocated each pass, but it adds up eventually.

Why is my variable not increasing after each recursion?

So I'm pretty new to C++ and I'm trying to generate Fibonacci numbers using recursion right? Except when I try to index to the next value I need to increase the index, and the function won't let me increase it.
How I know, is that I've run it in debug mode and stepped over the function - it continuously loops inside the fibGen function with i staying at a constant value of 1 (When I call fibGen in my main function the parameters are (startingSeq, 1, 13), where startingSeq is another vector with values {1,1}
The code builds and compiles fine, but when I run it I get a memory alloc error, which is obv caused by the infinite loop it seems to have.
What have I done wrong? Why doesn't the 'i' increase?
I've tried increasing i by having i++ inside the recursive fibGen call (in the else statement), I've tried having i++ outside the function call, and I've tried what's in there right now, where I have i+=1 and then pass i through.
Also I didn't have the 'return fibSeq' down the bottom originally because it doesn't make sense to have it there, but I put it in because vscode wouldn't compile without it in there, saying that it could never reach the end of fibGen (which makes sense now, and when this problem's fixed I think it can be removed, but at the moment it's just there so that the program will compile)
std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max){
if(fibSeq[i] >= max){
return fibSeq;
}else{
fibSeq.push_back(fibSeq[i] + fibSeq[i-1]);
i+=1;
fibGen(fibSeq, i, max);
}
return fibSeq;
}
The output should be a vector containing the Fibonacci sequence, and I'm getting a mem alloc error (described above)
Actually, your code kind of works. You are just handling the vector of results sub-optimally. With your declaration:
std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max)
you will always pass copies of the vector around (and you are never using the returned value). Instead, what you probably want to do is to work on the same data. To do this, use a reference to a vector (denoted by &). Then, you do not need to return anything:
void fibGen(std::vector<int>& fibSeq, int i, int max) {
if (fibSeq[i] >= max) {
return;
}
else {
fibSeq.push_back(fibSeq[i] + fibSeq[i - 1]);
i += 1;
fibGen(fibSeq, i, max);
}
}
void main(void) {
std::vector<int> fib = { 1, 1 };
fibGen(fib, 1, 34);
for (auto i : fib)
std::cout << i << std::endl;
}
So, I could not reproduce the error, until I realized that in your actual code, you were doing this instead of the code you posted:
std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max){
if(fibSeq[i] >= max){
return fibSeq;
}else{
fibSeq.push_back(fibSeq[i] + fibSeq[i-1]);
i+=1;
fibGen(fibSeq, i, max);
}
}
In Visual Studio 2010, at least, it compiled fine, but threw an error at runtime, which I believe is what you described. So I'm going to assume I reproduced it.
The reason this is throwing an error is because you are invoking C++'s infamous undefined behavior. Undefined behavior in C++ permits anything to happen, like not failing to compile, but throwing a runtime error.
The fix is simple, really. You just need to return a value in all execution paths. Or, simply put, just do this:
std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max){
if(fibSeq[i] >= max){
return fibSeq;
}else{
fibSeq.push_back(fibSeq[i] + fibSeq[i-1]);
i+=1;
return fibGen(fibSeq, i, max);
// Notice we are returning the value of the recursive call to fibGen().
// We can do this because we have already modified the vector the way we need to,
// so just simply returning the value is fine
}
}
Of course, you can take Nico Schertler's suggestion instead too:
void fibGen(std::vector<int>& fibSeq, int i, int max) {
if (fibSeq[i] >= max) {
return;
}
else {
fibSeq.push_back(fibSeq[i] + fibSeq[i - 1]);
i += 1;
fibGen(fibSeq, i, max);
}
}
It should be noted that not returning a value from a void function is not undefined behavior (that I'm aware), but actually how void's intended to work, so this function is fine not returning a value.

Dynamic Programming, Traversal Method

int fib(int numb){
vector<int> temp;
int str;
if(numb==0 || numb==1){
return numb;
}
else{
str=(fib(numb-1)+fib(numb-2));
temp.push_back(str);
return str;
}
for(int i=0;i<temp.size();i++){
if(temp[i]==numb){
return temp[i];
}}
Fibonacci function and it work but how do I check if the for loop part of the function really works? Its for a traversal method of finding a existing number and returning it instead of processing another recursion.
Your loop can't possibly work. It will never work. Because there's no way to get to the loop. Every code path before the loop ends with a return statement.
Walk through your code, statement by statement, and see for yourself that your code will never reach the loop.
You must process the stored elements before returning any value. More, as you store elements in vector during recursive calls, the vector temp must be static.
And the research should not be that: you should store in the vector the values, said differently, what you want it temp[i] is fib(i).
A simple way to do that is to make use that C++ allows initializing of static values through functions. You could then initialize temp to { 0, 1}, and when asked for a value, just look if the number is higher than temp.size:
if it is, compute it and store it into temp - as you compute them with values of fib(n-1) and fib(n-2), when you compute it you know that the temp vector already contains fib(n-1), and does not still contains fib(n) => you have just to push it back into temp
it not just extract it from temp
Code could be:
// return a temporary vector containing 0 and 1
std::vector<int> inifib() {
std::vector<int> t;
t.push_back(0);
t.push_back(1);
return t;
}
int fib(unsigned int numb) {
static std::vector<int> temp = inifib(); // initialize once the static temp with size 2 and values 0,1
if (numb >= temp.size()) {
int cr = fib(numb-1) + fib(numb - 2);
temp.push_back(cr); // when we are here, temp contains everything up to fib(numb - 1) - just push
}
return temp[numb];
}

Recursive Function Error

Im trying to create a recursive function that contains a vector of numbers and has a key, which is the number we are looking for in the vector.
Each time the key is found the function should display a count for how many times the key appears in the vector.
For some reason my recursive function is only returning the number 1 (disregard the 10 I was just testing something)
Here's my code:
int recursive_count(const vector<int>& vec, int key, size_t start){
if (start == vec.size())
return true;
return (vec[start] == key? 23 : key)
&& recursive_count(vec, key, (start+1));
}
int main() {
vector <int> coco;
for (int i = 0; i<10; i++) {
coco.push_back(i);
}
cout << coco.size() << endl;
int j = 6;
cout << recursive_count(coco, j, 0) << endl;
}
Not sure what you are trying to do, but as is - your function will return false (0) if and only if the input key is 0 and it is in the vector. Otherwise it will return 1.
This is because you are basically doing boolean AND operation. The operands are true for all values that are not 0, and the only way to get a 0 - is if it is in the vector - and the key is 0.
So, unless you get a false (0) along the way, the answer to the boolean formula is true, which provides the 1.
EDIT:
If you are trying to do count how many times the key is in vec - do the same thing you did in iterative approach:
Start from 0 (make stop condition return 0; instead of return true;)
Increase by 1 whenever the key is found instead of using operator&&, use the operator+.
(I did not give a direct full answer because it seems like HW, try to follow these hints, and ask if you have more questions).
To me it seems that a recursive function for that is nonsense, but anyway...
Think about the recursion concepts.
What is the break condition? That the current character being checked is not in the string anymore. You got that right.
But the recursion case is wrong. You return some kind of bool (what's with the 23 by the way?
The one recursion round needs to return 1 if the current element equals key, and 0 otherwise.
Then we only need to add up the recursion results, and we're there!
Here's the code
int recursive_count(const vector<int>& vec, int key, size_t start) {
if (start >= vec.size()) {
return 0;
} else {
return
((vec[start] == key) ? 1 : 0) +
recursive_count(vec, key, start+1);
}
}
Since this is even tail-recursion, good compilers will remove the recursion for you by the way, and turn it into its iterative counterpart...
Your recursive_count function always evaluates to a bool
You are either explicitly returning true
if (start == vec.size())
return true;
or returning a boolean compare
return (vec[start] == key? 23 : key) // this term gets evaluated
&& // the term above and below get 'anded', which returns true or false.
recursive_count(vec, key, (start+1)) // this term gets evaluated
It then gets cast to your return type ( int ), meaning you will only ever get 0 or 1 returned.
As per integral promotion rules on cppreference.com
The type bool can be converted to int with the value false becoming
​0​ and true becoming 1.
With,
if (start == vec.size())
return true;
your function with return type int returns 1

C++ int array pointers recursively to find prime factors

I am trying to make a function that can return the prime factors of a given number in an array (or multi-set, but I'm trying to use an array).
For example, if I put in 12, I want to get 2, 2, and 3, not 2, and 3 like with a set. This is so that I can use these to see if it is a Smith number or not, so I need the numbers seperately.
Also, I am taking a recursive approach.
I have tried (to no avail) to return the array many ways, including passing an initial pointer into the code which points to a space to store the array.
I've tried just initializing the array in the function and then returning it.
From what I can tell, I can get the array back from the base case iteration and then when trying to construct a new array with size oldArray+1 to copy values to, things get messy. This is where I get lost.
From what I've read, although this isn't the most efficient implementation, I should be able to make it work.
I have a function, nextPrime(int n), which given n will give back the next prime up from that number.
See source below:
int* find(int n, int p) {
int root = (int) floor(sqrt(n));
if (p > root) {
// Base case, array gets initialized and returned
// depending on value of n and p.
if (n > 1) {
factors = new int[1];
factors[0] = n;
return factors;
}
else {
factors = new int[0];
return factors;
}
}
else
if (n%p == 0){
// Inductive step if p is a factor
int newFloor = (int) floor(n/p);
factors = find(newFloor, p);
// Initialize new array.
int* newFactors;
newFactors = new int[(sizeof(factors) / sizeof(int)) + 1];
// Add p to first slot, fill rest with contents of factors.
factors[0] = p;
for (int i = 0; i < (sizeof(factors) / sizeof(int)); i++) {
newFactors[i+1] = factors[i];
}
return newFactors;
}
else {
// Inductive step p isn't a factor of n
factors = find(n, factors, nextPrime(p));
return factors;
}
}
As I say, the error is with returning the array and using its value, but why does it seem to return OK from the first iteration?
Something like this could work. Not terribly efficient !!
void FindFactors( int number , std::vector<int>& factors )
{
for ( int i = 2; i <= number; ++i )
{
if ( number % i == 0 )
{
factors.push_back( i );
FindFactors( number / i , factors);
break;
}
}
}
int main()
{
std::vector<int> factors;
FindFactors( 121 , factors );
return 0;
}
After you call the function factors will contain only the prime factors.
You should be using std::vector for this. The main problem you have is that a pointer to an array has no way of knowing the number of items the array contains. Concretely, the part where you say sizeof(factors) is wrong. As I understand, you're expecting that to give you the number of items in the array pointed to by factors, but it really gives you the number of bytes needed to store a pointer to int.
You should be either returning a vector<int> or passing it in as a reference and updating it each time you find a factor.