Recursive function to check all pairs in an array - c++

an int vector is given, and I need to find the maximum sum of number sequences that are more than 3 positions away from each other. So an example:
Input: 10, 5, 6, 7, 16, 18, 12
Output: 29
Explanation:
candidate "routes":
10-7-12 = 29
10-16 = 26
10-18 = 28
5-16 = 21
5-18 = 23
5-12 = 17
...
16
18
12
I want to solve this problem using recursion and I have gotten to the point where the program tests all paths with numbers that are more than 3 positions away. However, it fails to test all the paths starting from the same digit.
Here my code:
#include <iostream>
using namespace std;
const int n = 7;
int sum = 0;
int temp=0;
void rec(int (*arr), int ind){
if (ind > n-3){
if(temp > sum)
sum = temp;
temp=0;
return;
}
temp += arr[ind];
cout<<arr[ind]<<" ";
for(int i=3;i<n;i++)
rec(arr, ind+i);
cout<<endl;
}
int main(){
int arr[n] = {10, 9, 9, 9, 8, 8, 7};
for(int i=0;i<n;i++)
rec(arr, i);
cout<<endl<<endl<<"Max: "<<sum;
return 0;}
Output:
10 9 7
8
8
7
9 8
8
7
9 8
7
9 7
8
8
7
Max: 26
Even though in this case the output is correct, you can see that it tests only 10-9-7 and not the other 10-8, 10-8 and 10-7. It seems it doesn´t even go in the first for-loop I called the function recursively.
Am I understanding something wrong or how do I accomplish that it tests all pairs that are more than 3 positions away?

There are 3 problems here:
Based on your output:
10 9 7
8
8
⋮
Your code actually loops through all the possible routes. Instead of thinking your second line 8 and third line 8 as two complete routes, they were actually derived from your first rout 10 9 7. So really think of it like this:
10 --- 9 --- 7
`- 8
`- 8
`- 7
9 --- 8
`- 8
`- 7
⋮
That's actually not your output. Plugged your code in, I got my output:
10 9
8
9 8
9
9
8
Max: 19
The reason that it didn't go through all routes is because your line:
if (ind > n-3)
{
⋮
return;
}
You are terminating your loop way too early. Instead, you should only end it right before it goes out of index. So it should be:
if (ind > n - 1)
{
⋮
}
Your logic actually has flaws.
Because you always set your temp back to 0 once reached the last possible number inside the array, you actually lost some part of your previous sums. You can easily create a sequence that makes it fails, such as: 10, 9, 9, 7, 8, 20, 7.
Instead of having temp as a global, it would be better to set it local, and being passed to each recursions.
To do that, you would need to add the temp as a parameter of your rec function, and call it like:
void rec(int (*arr), int ind, int temp)
{
⋮
rec(arr, i, temp);
⋮
}
int main()
{
⋮
rec(arr, i, 0);
⋮
}
Or if you want to keep the signature the same in your main, you could also add a default argument in your rec:
void rec(int (*arr), int ind, int temp = 0)
Side note, I would considering using std::array or std::vector instead of c-style array, to avoid having a global size n or passing int (*arr) in your function. Plus you can easily make your arr as a longer sequence.

Related

Pointer to portions of array

I have an object of std::vector<std::array<double, 16>>
vector entry Data
[0] - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
[1] - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
[2] - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
[...] - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
This is intended to represent a 4x4 matrix in ravel format.
To not duplicate information I would like to create a pointer to extract a 3x3 from the above structure:
I have mathematical operations for the 3x3 structure (std::array<double, 9>)
someStructure: pointing to data elements [0, 1, 2, 4, 5, 6, 8, 9 10]
The end goal is do: std::array<double, 9> tst = someStructure[0] + someStructure[1];
Is this doable?
Best Regards
The 3x3 part is not contiguous, hence a pointer alone wont help here.
You can write a view_as_3x3 that allows you to access elements of the submatrix of the 4x4 as if it was contiguous:
struct view_as_3x3 {
double& operator[](size_t index) {
static const size_t mapping[] = {0, 1, 2, 4, 5, 6, 8, 9, 10};
return parent[mapping[index]];
}
std::array<double, 16>& parent;
};
Such that for example
for (size_t = 0; i< 9; ++i) std::cout << " " << view_as_3x3{orignal_matrix}[i];
is printing the 9 elements of the 3x3 sub-matrix of the original 4x4 original_matrix.
Then you could more easily apply your 3x3 algorithms to the 3x3 submatrix of a 4x4 matrix. You just need to replace the std::array<double, 9> with some generic T. For example change
double sum_of_elements(const std::array<double, 9>& arr) {
double res = 0;
for (int i=0;i <9; ++i) res += arr[i];
return res;
}
To:
template <typename T>
double sum_of_elements(const T& arr) {
double res = 0;
for (int i=0;i <9; ++i) res += arr[i];
return res;
}
The calls are then
std::array<double, 16> matrix4x4;
sum_of_elements(view_as_3x3{matrix4x4});
// or
std::array<double, 9> matrix3x3;
sum_of_elements(matrix3x3);
It would be nicer to use iterators instead of indices, however, writing the view with custom iterators requires considerable amount of boilerplate. On the other hand, I would not suggest to use naked std::arrays in the first place, but rather some my_4x4matrix that holds the array as member and provides iterators and more convenience methods.

Getting funny output for insertion sort

I'm trying to implement insertion sort. My logic may be wrong because I was unable to complete my code due to some error.
I want help with values changing absurdly while executing. Also, there is a similar repeating element question but it is in python and it went over my head. so, please don't mark it duplicate.
As you can see I have initialized a temporary variable index, why you ask? because the value of N is changing during run time.
secondly, Value is getting repeated when sorting is taking place.
I'm using codeblocks 17.2.
#include<iostream>
#include<utility>
#include<algorithm>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
int arr[100];
int N,index;
cin>>N;
for(int i=0;i<N;i++)
{
cin>>arr[i];
}
index=N; // using temperory variable
for(int l=0;l<index;l++)
{
for(int j=l+1;j>=0;j--)
{
if(l==index-1 || j==0) //Working fine now
break;
if(arr[j]<arr[j-1])
{
swap(arr[j],arr[j-1]);
}
}
cout<<N<<endl; //value of n is changing but why
for(int k=0;k<index;k++)
{
cout<<arr[k]<<" "; //value of array is also coming wrong
}
cout<<"\n";
}
return 0;
}
N=7
and elements of the array to be
7 8 5 2 4 6 3
output is
7 //these are the values of N which is changing
7 8 5 2 4 6 3
5
7 7 8 2 4 6 3
2
5 7 7 8 4 6 3
2
4 5 7 7 8 6 3
2
4 5 6 7 7 8 3
2
3 4 5 6 7 7 8
0
2 3 4 5 6 7 7
check for boundary condition and when non-existing array index is accessed it will give undefined behavior. In this case, it appears that N was stored right before arr and it changed when you modified arr[-1].

Is there any way to add numbers to a "buffer" in a while-loop?

I'm pretty new to c++, and at the moment i am trying to make a calculator that calculates a Euklid's Algorithm.
Anyways, what i need help with is how i can add the final number to some kind of array for each loop.
Lets for example say i put in the numbers 1128 and 16. my program will then give this output
1128 % 16 = 70 + 8
70 % 16 = 4 + 6
4 % 16 = 0 + 4
theese three lines is printed, one at the time, for each loop. What i want is to add the last numbers (8, 6 and 4) to an array. How would i do this?
Use Vector instead of array, Hope this Helps!
#include <iostream>
#include<vector>
using namespace std;
int main()
{
int a=1128,b=16,i;
vector<int>arr;
while(a>b)
{
cout<<a/b<<" "<<a%b<<endl;
arr.push_back(a%b);
a/=b;
}
cout<<a/b<<" "<<a%b<<endl;
arr.push_back(a%b); // Case: When a<=b in Vector
for(i=0;i<arr.size();i++)
cout<<arr[i]<<" "; // Array i.e 8 6 4
return 0;
}
Output:
70 8
4 6
0 4
8 6 4 // Array

next greater element in array

#include<iostream>
#include <stack>
using namespace std;
void printNextGreaterElement(int input[], int inputSize) {
stack<int> s;
s.push(input[0]);
for (int i = 1; i < inputSize; i++) {
while (!s.empty() && s.top() < input[i]) {
cout<<"Next greater element for "<<s.top()<<"\t = "<<input[i]<<"\n";
s.pop();
}
s.push(input[i]);
}
while (!s.empty()) {
int top = (int) s.top();
s.pop();
cout<<"Next greater element for "<<top<<"\t = null\n";
}
}
int main() {
int input[] = { 98, 23, 54, 12, 20, 7, 27 };
printNextGreaterElement(input, 7);
return 0;
}
I was learning about NGE in the array and came across this piece of code which I found on geeksforgeeks and other websites, but isn't this gives wrong output for the test case:
14
10 3 12 4 2 9 13 0 8 11 1 7 5 6
Given an array, print the Next Greater Element (NGE) for every element. The Next greater Element for an element x is the first greater element on the right side of x in array.
Your code seems to be fine and gives the correct output of the input which you told gives wrong output is as following.
The input is as you mentioned
14
10 3 12 4 2 9 13 0 8 11 1 7 5 6
The output is
Next greater element for 3 = 12
Next greater element for 10 = 12
Next greater element for 2 = 9
Next greater element for 4 = 9
Next greater element for 9 = 13
Next greater element for 12 = 13
Next greater element for 0 = 8
Next greater element for 8 = 11
Next greater element for 1 = 7
Next greater element for 5 = 6
Next greater element for 6 = null
Next greater element for 7 = null
Next greater element for 11 = null
Next greater element for 13 = null
For example, the second element in the array is 3, the next greater element in the array is 12 (Which is the output).
The explanation of the algorithm is not given here as it is well written in the post you mentioned.

C++ negative array indices

I want to loop an array then during each loop I want to loop backwards over the previous 5 elements.
So given this array
int arr[24]={3, 1, 4, 1, 7, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4}
and this nested loop
for(int i=0;i<arr.size;i++)
{
for(int h=i-5; h<i; h++)
{
//things happen
}
}
So, if i=0, second loop would loop last few elements 4,6,2,6,5.
How could you handle this?
I'm assuming that:
You only want to go over previous values (i.e. no wrap around) You
You don't actually want arr to be a multi-dimensional array as suggested
by your choice of tags
You want to include the current i in your five values
This is just a small modification to your code that will do (what I think) you are asking:
#include <math>
int main()
{
int arr[24]={3, 1, 4, 1, 7, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4}
for(int i=0;i<arr.size;i++)
{
for(int h = max(i-4, 0); h < i+1; h++)
{
//things happen
}
}
}
note the h = max(i-4, 0) and h < i+1This will reduce the number of iterations of the inner loop so that it starts from index 0 and loops up through the five values up to and including i. (four values and i). h will always be within bounds.
The case where i==arr.size won't be a problem in the inner loop as the outer loop will terminate before that happens (i is always within bounds).
Edit: I saw this comment:
I want the first element to consider the last final 5 elements of the array though.
in which case, your loops should look like:
for(int i=0;i<arr.size;i++)
{
for(int h=0; h<5; h++)
{
int index = (i + arr.size - h) % arr.size;
//things happen
//access array with arr[index];
}
}
This should do what you want:
When i=0, h=0 index=(0+24-0)%24 which is 0. For h=1 we go one less, index=(0+24-1)%24 = 23 and so on for the next values of h.
The code gets the last 5 values, wrapping round, inclusive of the current value. (so will get 20,21,22,23,0 when i=0, 21,22,23,0,1 when i=1)
If you want the five before, non-inclusive, then inner loop should be:
for(int h=1; h<=5; h++)
here is the current output of the loop as it stands:
i 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 ... 22 22 22 22 22 23 23 23 23 23
h 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 ... 0 1 2 3 4 0 1 2 3 4
index 0 23 22 21 20 1 0 23 22 21 2 1 0 23 22 3 2 1 0 23 ... 22 21 20 19 18 23 22 21 20 19
I assume you want it to loop around (don't know why). if so, use modulo:
int index = (h + arr.size) % arr.size;
Using the modulo operator.
for (int i = 0; i < arr.size; i++)
{
for (int h = 5; h > 0; h--)
{
const int array_length = sizeof(arr) / sizeof(arr[0]);
int index = (i - h + array_length) % array_length; // Use 'sizeof(arr) / sizeof(arr[0])' to get the size of the array
//things happen
}
}
Is using if statement not an option?
const int array_size = 24;
int arr[array_size] = { 1,3,4,5,...,2 }
for(int i=0;i<array_size;i++)
{
for(int h=i-5; h<i; h++)
{
int arr_index = (h >= 0) ? h : (array_size + h);
//do your things with arr[arr_index]
}
}
you may also start the nested loop with something like:
for(int h=i-min(i,5);h<i;++h)
{
}
which let you process first 5 cells as well. also, if you are dealing with some kind of signal or image processing consider extending arr to have 29 elements with preceding 5 zeros or whatever value would be suitable, and start the first for-loop with 5th element.
Just make an if statement in nested loop. Something like this
for( int h = i-5; h < i; h++ )
{
// do stuff
if( i == 0 )
break;
}