How to call a function containing multidimensional array? - c++

#include <iostream>
#define MAX 100
using namespace std;
void compute_minor_sums (int a[][MAX], int B[][MAX], int n1, int n2){
int sum=0,row[n2],col[n1];
for(int i=0;i<n1;i++){
for(int j=0;j<n2;j++){
cin>>a[i][j];
sum+=a[i][j];
}
}
for(int i=0;i<n1;i++){
for(int j=0;j<n2;j++){
row[i]+=a[i][j];
col[j]=col[j]+a[i][j];
}
}
for(int i=0;i<n1;i++){
for(int j=0;j<n2;j++){
B[i][j]=sum-row[i]-col[j]+a[i][j];
}
}
}
int main()
{
int n1,n2;cin>>n1>>n2;
int a[n1][n2],B[n1][n2];
compute_minor_sums ( a, B,n1,n2);
}
Program is about computing minor of an n1*n2 matrix.
I tried calling a function which computes minor.But I don't know exactly why is this giving these kind of errors? The first errors is:
Cannot convert int (*)[n2] to int int (*)[100]
The second error is:
Initialising argument 1 of void compute_minor_sums (int a[][MAX], int B[][MAX], int n1, int n2)
I can't use gdb as these errors are syntax errors.
Any help would be appreciated

The code is rewritten with vector.
(I'm not sure about matrix calculation logic.)
There would be memory bound errors if matrices are not square.
#include <iostream>
#include <vector>
#define MAX 100
using namespace std;
void compute_minor_sums(vector<vector<int>>& a, vector<vector<int>>B, int n1, int n2) {
int sum = 0;
vector<int> row(n2);
vector<int>col(n1);
for (int i = 0; i < n1; i++) {
for (int j = 0; j < n2; j++) {
cin >> a[i][j];
sum += a[i][j];
}
}
for (int i = 0; i < n1; i++) {
for (int j = 0; j < n2; j++) {
row[i] += a[i][j];
col[j] = col[j] + a[i][j];
}
}
for (int i = 0; i < n1; i++) {
for (int j = 0; j < n2; j++) {
B[i][j] = sum - row[i] - col[j] + a[i][j];
}
}
}
int main()
{
int n1, n2;
cin >> n1 >> n2;
vector<vector<int>> a(n1, vector<int>(n2)); // n1 x n2 matrix
vector<vector<int>> B(n1, vector<int>(n2)); // n1 x n2 matrix
compute_minor_sums(a, B, n1, n2);
}

There are many issues with your code, I'll start with the few that are visible. As other users have mentioned in the comments - VLA doesn't exist in C++. What is a VLA?
The size of VLA's is determined during runtime and not during compilation. So the following code won't compile because values n1 and n2 are determined during runtime by the user.
int main()
{
int n1,n2;
std::cin >> n1 >> n2; // <-- we get values n1 and n2 during runtime from user input
int a[n1][n2],B[n1][n2];
//...
}
The following code will compile:
int main()
{
const int n1 = 1;
const int n2 = 2; // known during compilation and guaranteed not to change
int a[n1][n2],B[n1][n2];
int c[1][2]; // the same as using const ints - 1 and 2 are known during compilation
//...
}
So you might be asking:
What can we do if we do not know the size of the C-style array during compilation?
The answer is, you can allocate the array on the heap, however to have a 2D array is no longer simple, i.e.:
int main()
{
int n1,n2;
std::cin >> n1 >> n2; // <-- we get values n1 and n2 during runtime from user input
int **a = new int*[n1];
for (int i = 0; i < n1; ++i) {
a[i] = new int[n2];
}
}
We are as you can see creating pointers to pointers to int. Because array is just that - a pointer to an int which is the beginning of the array of int and the rest of the values are just offsets of the previous element.
We can also simplify the above by doing the following:
int* a = new int[n1 * n2];
// a[i][j] is then
a[i * n1 + j]
There are other issues with your code, but one thing at a time.
If you wish to pass it to the function, well you have more options now, but simply passing the pointer to the beginning of the array (i.e. a) is sufficient, however then you have to add some additional bound-checking logic. Hence why one of the answers suggested an std container called std::vector because these containers do all of this for you, with minimal overhead.
EDIT: The other issues with your code are for example here:
row[i]+=a[i][j];
col[j]=col[j]+a[i][j];
You do not initialize these arrays in your code, I'll be honest I'm not sure what is the default defined behavior for non-VLAs but when you allocate something on the heap as mentioned in my answer. You will get (most-likely) into undefined-behavior land with random values. So be sure to initialize row/col with default values (since you are doing mostly additions, you want to initialize with 0s)

Related

what's wrong with this "maximum-minimum element in an array" Logic?

I am new to coding and I am unable to see what is wrong with this Logic.
I am unable to get the desired output for this program.
The Question is to find the minimum and maximum elements of an array.
The idea is to create two functions for minimum and maximum respectively and have a linear search to identify the maximum as well as a minimum number.
#include <iostream>
#include<climits>
using namespace std;
void maxElement(int a[], int b)
{
// int temp;
int maxNum = INT_MIN;
for (int i = 0; i < b; i++)
{
if (a[i] > a[i + 1])
{
maxNum = max(maxNum, a[i]);
}
else
{
maxNum = max(maxNum, a[i+1]);
}
// maxNum = max(maxNum, temp);
}
// return maxNum;
cout<<maxNum<<endl;
}
void minElement(int c[], int d)
{
// int temp;
int minNum = INT_MAX;
for (int i = 0; i < d; i++)
{
if (c[i] > c[i + 1])
{
minNum = min(minNum,c[i+1]);
}
else
{
minNum = min(minNum,c[i]);
}
// minNum = min(minNum, temp);
}
// return minNum;
cout<<minNum<<endl;
}
int main()
{
int n;
cin >> n;
int arr[n];
for (int i = 0; i < n; i++)
{
cin >> arr[i];
}
minElement(arr,n);
maxElement(arr,n);
return 0;
}
You are already comparing each element to the current max / min. It is not clear why in addition you compare to adjacent elements. Trying to access a[i+1] in the last iteration goes out of bounds of the array and causes undefined behavior. Just remove that part:
void maxElement(int a[], int b)
{
// int temp;
int maxNum = INT_MIN;
for (int i = 0; i < b; i++)
{
maxNum = max(maxNum, a[i]);
}
cout<<maxNum<<endl;
}
Similar for the other method.
Note that
int n;
cin >> n;
int arr[n];
is not standard C++. Variable length arrays are supported by some compilers as an extension, but you don't need them. You should be using std::vector, and if you want to use c-arrays for practice, dynamically allocate the array:
int n;
cin >> n;
int* arr = new int[n];
Also consider to take a look at std::minmax_element, which is the standard algorithm to be used when you want to find the min and max element of a container.
Last but not least you should seperate computation from output on the screen. Considering all this, your code could look like this:
#include <iostream>
#include <algorithm>
std::pair<int,int> minmaxElement(const std::vector<int>& v) {
auto iterators = std::minmax_element(v.begin(),v.end());
return {*iterators.first,*iterators.second};
}
int main()
{
int n;
std::cin >> n;
std::vector<int> input(n);
for (int i = 0; i < n; i++)
{
std::cin >> input[i];
}
auto minmax = minmaxElement(input);
std::cout << minmax.first << " " << minmax.second;
}
The method merely wraps the standard algorithm. It isnt really needed, but I tried to keep some of your codes structure. std::minmax_element returns a std::pair of iterators that need to be dereferenced to get the elements. The method assumes that input has at least one element, otherwise dereferencing the iterators is invalid.

How to insert product and sum between every two consecutive elements in an array

In a vector, I must insert product and sum between every two consecutive elements.For example the
1 2 3 4 vector will become 1 3 2 2 5 6 3 7 12 4.
This is the code i did till now.
You can see that the function which makes the insertion is insertInVector().
#include <iostream>
void sumProduct(int a, int b, int* suma_functie, int* produs_functie)
{
*suma_functie = a + b;
*produs_functie = a * b;
}
void insertInVector(int &n,int v[])
{
int suma, produs;
for (int i = 1; i <= n; i++)
{
sumProduct(v[i], v[i + 1], &suma, &produs);
v[i + 4] = v[i + 1];
v[i + 1] = suma;
v[i + 5] = v[i + 2];
v[i + 2] =produs ;
}
}
void readVector(int n, int v[])
{
for (int i = 1; i <= n; i++)
std::cin >> v[i];
}
void displayVector(int& n, int v[])
{
for (int i = 1; i <= n; i++)
std::cout << v[i]<<" ";
}
int main()
{
int n,v[100];
std::cin >> n;
readVector(n, v);
insertInVector(n, v);
displayVector(n, v);
}
I changed some things in your code. One of the main things is that you can't insert in the middle of an array as it has a static memory (if you want to change only in the given array without using anything extra then you should use vector instead of array). So for this purpose, I have used an extra temp array and reflected those changes in the original array at the end. Also, I used pass by reference in the function sumProduct as I am not aware of the way you were using it; you can change it if you want. Also n+(2*(n-1)) is the new length of the array which can easily be predicted from the question. Just check out the changes in insertInVector function you will understand the rest.
#include <iostream>
void sumProduct(int a, int b, int& suma_functie, int& produs_functie)
{
suma_functie = a + b;
produs_functie = a * b;
}
void insertInVector(int &n,int v[])
{
int suma, produs;
int temp[100];
for (int i = 1, j=1; i <= n-1; i++)
{
temp[j]=v[i];
sumProduct(v[i], v[i + 1], suma, produs);
temp[j+1]=suma;
temp[j+2]=produs;
j+=3;
}
int n2=n;
n=n+(2*(n-1));
temp[n]=v[n2];
for (int i=1; i<= n; i++)
{
v[i]=temp[i];
}
}
void readVector(int n, int v[])
{
for (int i = 1; i <= n; i++)
std::cin >> v[i];
}
void displayVector(int& n, int v[])
{
for (int i = 1; i <= n; i++)
std::cout << v[i]<<" ";
}
int main()
{
int n,v[100];
std::cin >> n;
readVector(n, v);
insertInVector(n, v);
displayVector(n, v);
}
Hope it helps!
User8411584 is completely correct in pointing out that you need to create a temporary copy of the array first instead of simply beginning to overwrite it.
Just a little addition though:
The term for the new length of the resulting array n+(2*(n-1)) can be simplified to 3n-2.

How to run this code in less than 1 second?

How can I solve this problem without getting time limit exceeded
http://codeforces.com/problemset/problem/474/B
I tried putting all ranges in a 2D vector then looking for the desired index using binary search but it seems that the loop in the fn BS() takes a lot to execute as the size of the vector can be 10^6.
here is my code:
#include <iostream>
#include <vector>
using namespace std;
int Search(vector <vector<int> > a,int key){
int start = 0;
int end = a.size() - 1;
while (start <= end){
int mid = start + (end - start) / 2;
if (a[mid][0] > key && a[mid][1] > key){
end = mid - 1;
}
else if (a[mid][0] < key && a[mid][1] < key){
start = mid + 1;
}
else {
return mid;
}
}
return -1;
}
vector <int> BS(vector <vector <int> > v, vector<int> keys){
int j = 0;
vector <int> piles;
for (int i = 0; i < keys.size(); i++){
piles.push_back(Search(v, keys[i])+1);
}
return piles;
}
vector < vector<int> > Range(vector<int> v){
vector < vector<int> > ranges(v.size());
int sum1 = 1;
int sum2 = v[0];
for (int i = 0; i < v.size(); i++){
if (i == 0){
ranges[i].push_back(sum1);
ranges[i].push_back(v[i]);
sum1 += v[i];
}
else{
ranges[i].push_back(sum1);
sum2 += v[i];
ranges[i].push_back(sum2);
sum1 += v[i];
}
}
return ranges;
}
int main(){
int n, m;
cin >> n;
vector <int> a, q;
vector < vector <int> > v;
for (int i = 0; i < n; i++){
int k;
cin >> k;
a.push_back(k);
}
cin >> m;
for (int i = 0; i < m; i++){
int l;
cin >> l;
q.push_back(l);
}
v = Range(a);
vector <int> jucy = BS(v, q);
for (int i = 0; i < jucy.size(); i++){
cout << jucy[i] << endl;
}
}
In fact i don`t think you need 2D vector at all, you need just 1D. Which for example would look like this [2,9,12,16,25], the upper bound of each pile, you can construct this really easy. Then for every juicy worm you do binary search in that manner that it returns index with value greater or equal to the value you are looking for. The index you got from the search is the pile you are looking for.
Some pseudo-code:
A[n] - vector of upper bounds
A[0] = a0
For each 0<i<=n A[i]=A[i-1]+ai
For each q do std lower_bound on A looking for q,
the index you get is with first value equal or greater than q, so the pile where is q.
and C++ code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
int n, m;
cin >> n;
vector<int>A;
A.resize(n);
int ai;
cin >> ai;
A[0]=ai;
for (int i = 1; i < n; i++){
cin >> ai;
A[i]=A[i-1]+ai;
}
cin >> m;
int q;
for (int i = 0; i < m; i++){
cin >> q;
cout << std::distance(A.begin(),std::lower_bound(A.begin(),A.end(),q))+1<<endl;
}
return 0;
}
You have to add +1 to distance because the piles are numbered from 1. Work for the example, and looks pretty fast.
The most obvious optimization opportunity is, instead of using a vector<vector<int>> use a vector<int> and manually adjust the 2D indices to 1D. You can write a simple wrapper class that does this for you.
The reason that that will be much faster is that then all the memory will be allocated as a single contiguous unit. If you have a vector of vectors, then each row will be somewhere else and you'll have lots of cache misses.
Here's a code example:
struct 2D_Vector {
std::vector<int> me_;
int ncols_;
2D_Vector(int nrows, int ncols) : me(nrows * ncols), ncols_(ncols) {}
int & get(int y, int x) { return me_[y * ncols_ + x]; }
const int & get(int y, int x) const { return me_[y * ncols_ + x]; }
...
};
If you preallocate this with all the space that it will need, then it should use memory very efficiently.
Also, passing large function parameters by value instead of by reference is very wasteful, because it results in needless copies being made and destroyed. (Like WhozCraig pointed out.)

Can't get my pointers to send a reference to the array

#include<stdio.h>
#include<stdlib.h>
int* getEvenNumbers(int arr[], int N)
{
int i, k = 0 , a[50], p;
for (i = 0; i < N; i++)
{
if (arr[i] % 2 == 0)
{
arr[k]=arr[i];
k++;
}
}
return arr[k];
}
int main ()
{
int i, arr[5000000], N, a[500000], k, *p;
printf("\nEnter your desired length of the array:\n\n");
scanf("%d", &N);
for (i = 0; i < N; i++)
arr[i]= rand();
getEvenNumbers (arr, N);
printf("\n\nEven numbers in the array are as follows:\n\n");
for (i = 0; i < N; i++)
{
a[i]= *(p+i);
printf("\n[%d] = %d", (i+1), a[i]);
}
}
please i know this is probably very easy for you guys but i need help figuring out how to return a pointer to the array without all my values of my array getting deleted, also i can't use global variables and it has to be a function that returns a pointer pointing to the array
First of all, decrease the size of those arrays, you don't need that much space. Second of all, you made your
getEvenNumbers
function return an int *, and not an int. arr[k] is not an int *. I also don't get why you are returning something if nothing is being assigned when you call the function. You can just change the return type to void.
void getEvenNumbers(int arr[], int N)
You also never allocate any memory for p. You can do
p = (int*) malloc(sizeof(int));
And since you never allocated any memory for p, the following line of code
a[i]= *(p+i);
is assigning a[i] to a random address. You should just try to rewrite this program. There a lot of errors in this program that I didn't even correct. Go on Google an look up finding even numbers in array program or something similar and look at the code of those examples.
EDIT:
I found some code examples for you to use. I hope it helps!
StackOverflow
sanfoundry.com
The caller already knows the address of the array, so you just need to return the new length. If we also remove the unused variables and take advantage of C++ declarations, we will have:
int getEvenNumbers(int* arr, int N)
{
for (int i = 0, k = 0; i < N; i++) {
if (arr[i] & 1 == 0) { // even if lowest bit is zero
arr[k] = arr[i];
k++;
}
}
return k;
}
Now you can print the even numbers easily:
int k = getEvenNumbers(arr, N);
printf("\n\nEven numbers in the array are as follows:\n\n");
for (i = 0; i < k; i++) {
printf("\n[%d] = %d", (i+1), arr[i]);
}
Dynamically allocate memory from heap.
int* a= new int [N];
//Now store the elements from index 1.
// at a[0] store the number of even number you have found in this function.
return a;
In main you know how many even numbers are there.
int *a1=getEvenNumbers(arr,n);
count_even=a1[0];
for(index=1;index<=count_even;index++)
cout<<a1[index];
The code is given here-
#include<stdio.h>
#include<stdlib.h>
int* getEvenNumbers(int arr[], int N)
{
int i, k = 1 , p;
int* a=new int[N+1];
for (i = 0; i < N; i++)
{
if (arr[i] % 2 == 0)
a[k++]=arr[i];
}
a[0]=k-1;
return a;
}
int main ()
{
int i, N;
printf("\nEnter your desired length of the array:\n\n");
scanf("%d", &N);
int arr[N];
for (i = 0; i < N; i++)
arr[i]= rand();
int *a=getEvenNumbers (arr, N);
printf("\n\nEven numbers in the array are as follows:\n\n");
for (i = 1; i <= a[0]; i++)
printf("\n[%d] = %d", (i), a[i]);
delete []a;
}
A better option is to use std::vector.You can read it here.

C++ Merging 2 sorted arrays into 1 sorted

So I am trying so merge 2 sorted arrays into one and I get really weird numbers like an output. Here is my code:
#include<iostream>
using namespace std;
int* add(int first[],int second[], int sizeFirst, int sizeSecond)
{
int result[sizeFirst + sizeSecond];
int indexFirst = 0,indexSecond = 0;
for(int i = 0;i < sizeFirst + sizeSecond;i++)
{
if(indexFirst == sizeFirst || first[indexFirst] > second[indexSecond])
{
result[i] = second[indexSecond];
indexSecond++;
}
else
{
result[i] = first[indexFirst];
indexFirst++;
}
}
return result;
}
int main()
{
int n;
cin>>n;
int arr[n];
for(int i = 0;i < n;i ++)
cin>>arr[i];
int m;
cin>>m;
int arr2[m];
for(int i = 0;i < m;i ++)
cin>>arr2[i];
int *res;
res = add(arr,arr2,n,m);
for(int i = 0;i < n + m;i ++)
cout<<res[i]<<" ";
return 0;
}
Notes: It sorts it properly, so the mistake is not there. Also I need to do it as a function because I will need it later on for some other stuff.
return result;
You are returning a pointer to local array, which gets destroyed immediately after - this is undefined behavior. You should either allocate it using new or use std::vector (which is preferred).
Also, int result[sizeFirst + sizeSecond]; is not valid C++ because the standard doesn't allow variable sized arrays (but int* result = new int[sizeFirst + sizeSecond]; is valid).