Recursion in a for loop to iteration - c++

I am generalizing another problem I have that has a similar recursive call. In my case, the variables being used are strings, so I can't simply pass by value to avoid the code before and after the recursive call in the loop. Is there a way to turn this into an iterative loop? Please assume that the code before and after the recursive call in the loop cannot be changed to make this specific instance work.
This code tests to see if the sum of any combintion of ints from nums adds up to zero. The original value for index is 0, and max is the maximum number of numbers I want to add up in any given solution.
For further clarification, the numbers can be repeated, so I can't just try all possible combinations, because there are infinitely many.
void findSolution(const vector<int>& nums, vector<int>& my_list, int& mySum,
int index, const int max)
{
if(mySum == 0) {
/* print my_list and exit(0) */
}
if(index < max) {
for(int i = 0; i < nums.size(); ++i) {
my_list.push_back(nums[i]);
mySum += nums[i];
findSolution(nums, my_list, mySum, index+1, max);
mySum -= nums[i];
my_list.pop_back();
}
}
}

Maintain a manual stack.
In your case the only independent states of the recursive call are the value of I and the value of index. Index is just the recursive call depth.
Create a std vector of int called your stack, reserve it to max. Replace the loop with while stack true.
Before entering the loop, push zero on the stack.
Break the cod in your loop into 3 parts. A B and C. A is before recursive call, B is what you recursively call, and C is after. Included in C is the increment at the top of the loop, which happens after C in the original code.
The first thing you do in the loop is check if the top of the stack is nums size or bigger. If so, pop the stack, then execute C and continue unless stack is empty, in which case break.
Then execute A. Then push 0 on the stack and continue if the stack size is less than max. Then execute C. You can remove the C code duplication with a flag variable.
Remember that the top of the stack replaces any references to I. Basically we are replacing a recursive call which automatically makes a stack for us with manually maintaining the same stack, but only storing the absolute least amount we can get away with. The start of the loop does double duty as both the end of a recursive call and the start of the loop, so we can do away with goto.
Give it a try, and worry about the explanation after you have seen it. The stuff about the flag variable makes more sense after the code is in place.

Related

How can I stop a recursion from the base condition?

I am facing following problem with recursion. It is simple backtracking to print all the permutation, but I want to stop it from the base condition. For example, 4 character string will show 4!=24 strings. But I want to show first 20 strings only.
k is used for the purpose, k=20,for the example. Suppose, str="ABCD". I want to stop recursion after exactly 20 operations. How can I do this? I have tried to solve it in this way.
void permutation(string str,int l,int r,int k)
{
k--;
if(l==r||k==0) {
cout<<str<<endl;
return;
}
else{
for(int i=l;i<r;i++)
{
swap(str[l],str[i]);
permutation(str,l+1,r,k);
swap(str[l],str[i]);
}
}
}
If you want to use the unfortunately named k as a counter like that, it will count recursion levels, not results. If you want to count results, you need to store the counter outside of your function, either as a static or as a reference you pass to your function, and increment it every time you output a result.
You have two solutions to count the number of times results are printed:
1- Defining k as a global variable outside the function.
2- Defining k as a static variable: static int k = 0;.
Note that in both these solutions, k should be eliminated from the parameter list of the function.
I would also suggest choosing meaningful names for your variables. This way, it will be easier to understand and follow the code both for you and someone else who is going to help.

Heap Buffer Overflow occurs randomly....... for a simple code?(I'm new to C++)

ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000114 at pc 0x000000406d27 bp 0x7ffc88f07560 sp 0x7ffc88f07558
READ of size 4 at 0x602000000114 thread T0
LeetCode No.1
I get this when I give this code
The code below works for some other inputs, but for [3,2,4]\n6, it shows the above error.
vector<int> twoSum(vector<int>& nums, int target) {
int first = 0,last = nums.size() - 1;
vector<int> ref = nums;
while(first < last){
if(ref[first]+ref[last] > target) last--;
else if(ref[first]+ref[last] < target) first++;
else break;
}
vector<int> result;
for(int i=0;i<nums.size();i++){
if(ref[first]==nums[i]) result.push_back(i);
else if(ref[last]==nums[i]) result.push_back(i);
}
if(result[0] > result[1])
swap(result[0],result[1]);
return result;
}
The expected output is [1,2], indexes of values in the array adding up to the value 6.
Consider this while loop.
while(first < last){
if(ref[first]+ref[last] > target) last--;
else if(ref[first]+ref[last] < target) first++;
else break;
}
It seems that the intent was to break and exit when the sum is exactly equal to the target number. However, it is not guaranteed that this will become true. You can also exit the loop when the while condition fails, which happens whenever you reach first == last without yet finding any exact match. That actually happens in the particular case you mention. Follow the logic through and you will find this yourself. The search process misses the desired answer. The logic will not find [1,2]. It will first consider [0,2] and when that fails as too big, it will permanently decrement last and never again consider any combination that involves position 2.
(Likewise, if it fails for being too small it would increment the first position and never again consider combinations with the first value. So there are other failure cases that would happen similarly with that scenario.)
Since you exit without finding the matching combination and first == last, only one number will be pushed into the results. Therefore, when you just assume there are two numbers (false), things blow up as you try to reference the second result number.
General Observation:
You need to plan for the case where no exact match is found and code with that possibility in mind. In that case, what would a correct return result look like to signify no solution was found?
Plus, you could think about how the algorithm could be better at not missing a solution when it is actually present. However, that doesn't change the first requirement. If the target cannot be matched by any sum, you need to be ready for that possibility.
Side Notes:
Rather than repeat the sum of two in if statements, when the sum isn't changing I would suggest that you could create and use an auto local variable once that is
auto sum(ref[first]+ref[last]);
If you want to ensure that argument vector nums is not changed, and communicate that clearly to anyone looking at the declaration of the function, a better choice would be the pass it as a const reference, e.g.
(const vector<int>& nums, ...)
Why does the code create a local copy called ref of the argument vector nums? What is the point of making the effort to make the copy?
Regarding...
last = nums.size() - 1
...notice that if the vector passed in is empty, the value of last goes negative. That might not cause a problem for some code, but it has a dangerous smell in that it looks like code that is just assuming that the vector passed in would never be empty. Practice defensive coding that can be seen to guard against the possibility of unusual input values.
p.s. Part of what saves that last initialization from being broken is the use of int. Since size() returns size_t (unsigned), a common problem is to handle it as unsigned size_t. Then instead of going negative, the result wraps around to the maximum value and the looping may try to work with that as if that was a valid position in the vector. It's hazardous to get into habits that invite those kinds of bugs.

Should I refer std::vector size when the number is explicitly given

I'm coding a simple function using std::vector below where input is an integer vector and the function proceeds the iteration based on the number of elements in the vector.
In terms of space and time efficiency, which following code are suitable?
HugeClass is actually a Big Integer which contains complex arithmetic while I put a simple arithmetic below for simplicity.
1) Gives a dimension of vector
void (HugeClass& huge, std::vector<int>& vec, int dim){
for(int i=0;i<dim;i++){
huge+=vec[i];
}
}
2) Calls a std::vector.size() to iterate
void (HugeClass& huge, std::vector<int>& vec){
for(int i=0;i<vec.size();i++){
huge+=vec[i];
}
}
dim can range in [100,1000000]
The syntax of a for loop in C++ is:
for ( init; condition; increment ) {
statement(s);
}
Here is the flow of control in a for loop:
The init step is executed first, and only once. This step allows you to declare and initialize any loop control variables. You are not required to put a statement here, as long as a semicolon appears.
Next, the condition is evaluated. If it is true, the body of the loop is executed. If it is false, the body of the loop does not execute and flow of control jumps to the next statement just after the for loop.
After the body of the for loop executes, the flow of control jumps back up to the increment statement. This statement allows you to update any loop control variables. This statement can be left blank, as long as a semicolon appears after the condition.
So in the case of
for(int i=0;i<vec.size();i++) {
huge+=vec[i];
}
vec.size() called each time but is probably inlined, and is probably a simple function.
On top of which
A smart enough optimizer may be able to deduce that it is a loop invariant with no side effects and elide it entirely (this is easier if the code is inlined, but may be possible even if it is not if the compiler does global optimization)

Alternative to using mpfr arrays

I am trying to write a function in C++ using MPFR to calculate multiple values. I am currently using an mpfr array to store those values. It is unknown how many values need to be calculated and stored each time. Here is the function:
void Calculator(mpfr_t x, int v, mpfr_t *Values, int numOfTerms, int mpfr_bits) {
for (int i = 0; i < numOfTerms; i++) {
mpfr_init2(Values[i], mpfr_bits);
mpfr_set(Values[i], x, GMP_RNDN);
mpfr_div_si(Values[i], Values[i], pow(-1,i+1)*(i+1)*pow(v,i+1), GMP_RNDN);
}
}
The program itself has a while loop that has a nested for loop that takes these values and does calculations with them. In this way, I don't have to recalculate these values each time within the for loop. When the for loop is finished, I clear the memory with
delete[] Values;
before the the while loops starts again in which case, it redeclares the array with
mpfr_t *Values;
Values = new mpfr_t[numOfTerms];
The number of values that need to be stored are calculated by a different function and is told to the function through the variable numOfTerms. The problem is that for some reason, the array slows down the program tremendously. I am working with very large numbers so the thought is that if I recalculate those values each time, it gets extremely expensive but this method is significantly slower than just recalculating the values in each iteration of the for loop. Is there an alternative method to this?
EDIT** Instead of redeclaring the array over each time, I moved the declaration and the delete[] Values outside of the while loop. Now I am just clearing each element of the array with
for (int i = 0; i < numOfTerms; i++) {
mpfr_clear(Values[i]);
}
inside of the while loop before the while loop starts over. The program has gotten noticeably faster but is still much slower than just calculating each value over.
If I understand correctly, you are doing inside a while loop: mpfr_init2 (at the beginning of the iteration) and mpfr_clear (at the end of the iteration) on numOfTerms MPFR numbers, and the value of numOfTerms depends on the iteration. And this is what takes most of the time.
To avoid these many memory allocations by mpfr_init2 and deallocations by mpfr_clear, I suggest that you declare the array outside the while loop and initially call the mpfr_init2 outside the while loop. The length of the array (i.e. the number of terms) should be what you think is the maximum number of terms. What can happen is that for some iterations, the chosen number of terms was too small. In such a case, you need to increase the length of the array (this will need a reallocation) and call mpfr_init2 on the new elements. This will be the new length of the array for the remaining iterations, until the array needs to be enlarged again. After the while loop, do the mpfr_clear's.
When you need to enlarge the array, have a good strategy to choose the new number of elements. Just taking the needed value of numOfTerms for the current iteration may not be a good one, since it may yield many reallocations. For instance, make sure that you have at least a N% increase. Do some tests to choose the best value for N... See Dynamic array for instance. In particular, you may want to use the C++ implementation of dynamic arrays, as mentioned on this Wikipedia article.

How to implement tail calls in a custom VM

How can I implement tail calls in a custom virtual machine?
I know that I need to pop off the original function's local stack, then it's arguments, then push on the new arguments. But, if I pop off the function's local stack, how am I supposed to push on the new arguments? They've just been popped off the stack.
I take it for granted that we're discussing a traditional "stack-based" virtual machine here.
You pop off the current function's local stack preserving the still-relevant parts in non-stack "registers" (where the "relevant parts" are, clearly, the argument for the forthcoming recursive tail call), then (once all of the function's local stack and arguments are cleaned up) you push the arguments for the recursive call. E.g., suppose the function you're optimizing is something like:
def aux(n, tot):
if n <= 1: return tot
return aux(n-1, tot * n)
which without optimization might produce byte-code symbolically like:
AUX: LOAD_VAR N
LOAD_CONST 1
COMPARE
JUMPIF_GT LAB
LOAD_VAR TOT
RETURN_VAL
LAB: LOAD_VAR N
LOAD_CONST 1
SUBTRACT
LOAD_VAR TOT
LOAD_VAR N
MULTIPLY
CALL_FUN2 AUX
RETURN_VAL
the CALL_FUN2 means "call a function with two arguments". With the optimization, it could become sometime like:
POP_KEEP 2
POP_DISCARD 2
PUSH_KEPT 2
JUMP AUX
Of course I'm making up my symbolic bytecodes as I go along, but I hope the intent is clear: POP_DISCARD n is the normal pop that just discards the top n entries from the stack, but POP_KEEP n is a variant that keeps them "somewhere" (e.g. in an auxiliary stack not directly accessible to the application but only to the VM's own machinery -- storage with such a character is sometimes called "a register" when discussing VM implementation) and a matching PUSH_KEPT n which empties the "registers" back into the VM's normal stack.
I think you're looking at this the wrong way. Instead of popping the old variables off the stack and then pushing the new ones, simply reassign the ones already there (carefully). This is roughly the same optimization that would happen if you rewrote the code to be the equivalent iterative algorithm.
For this code:
int fact(int x, int total=1) {
if (x == 1)
return total;
return fact(x-1, total*x);
}
would be
fact:
jmpne x, 1, fact_cont # if x!=1 jump to multiply
retrn total # return total
fact_cont: # update variables for "recursion
mul total,x,total # total=total*x
sub x,1,x # x=x-1
jmp fact #"recurse"
There's no need to pop or push anything on the stack, merely reassign.
Clearly, this can be further optimized, by putting the exit condition second, allowing us to skip a jump, resulting in fewer operations.
fact_cont: # update variables for "recursion
mul total,x,total # total=total*x
sub x,1,x # x=x-1
fact:
jmpne x, 1, fact_cont # if x!=1 jump to multiply
retrn total # return total
Looking again, this "assembly" better reflects this C++, which clearly has avoided the recursion calls
int fact(int x, int total=1)
for( ; x>1; --x)
total*=x;
return total;
}