How to convert 2D array to 1D in C++? - c++

So for example I have a 2D array A={{1,2,3}, {2,3},{5}}; and I want to get all the rows existing in the array A. I have the length of array stored in variable "lenA", here lenA=3. Also I have an Array B which has the length of each subarray in A. Say B={3,2,1} in this case. In reference to my example array A, how to I dynamically get 3 subarrays from one 2D array i.e. A?
So as a result I would have something like:
A1={1,2,3}
A2={2,3}
A3={5}

You can't dynamically generate new identifiers in C++. The closest you can get is using the preprocessor to generate your names, and by definition, that's done before compilation.
If you already have a fixed number of named array pointers, you could assign those dynamically. But any solution that must accept an arbitrary number of rows at runtime will require that you use something like an array index.
for (int i = 0; i < lenA; i++)
{
// Do something with the row at A[i]
}

Pseudo code
for i in 0 to lenA-1
for j in 0 to lenB[i]-1
A[i][j] whatever...

My try converting A(4x4) to triangle *a[4]:
#include <iostream>
#include <algorithm>
int main()
{
constexpr int lenA = 4;
double A[lenA][lenA]={{1,2,3,4}, {5,6, 7, 0}, {8, 9,0,0},{10,0,0,0}};
double *a[lenA];
int B[lenA] = {4, 3, 2, 1};
for (int i=0; i < lenA; i++)
{
a[i] = new double [ B[i] ];
std::copy_n(A[i], B[i], a[i]);
}
for (int i=0; i<lenA; i++) {
std::cout << "row " << i << ": ";
for (int j=0; j<B[i]; j++) {
std::cout << a[i][j] << ". ";
}
std::cout <<std::endl;
}
return 0;
}
result:
$ ./a.exe
row 0: 1. 2. 3. 4.
row 1: 5. 6. 7.
row 2: 8. 9.
row 3: 10.

you can find the verification of the below code at http://cpp.sh/57pi2
A1D represent the 1-Dimensional array which you was looking for,
#include <iostream>
int main()
{
const int lenA = 4;
double A2D[][lenA]={{1,2,3,4},{5,6,7},{8,9},{10}};
double *A1D;
int B[lenA] = {4,3,2,1};
int num_of_elements = 0;
for (int i=0; i < lenA; i++)
num_of_elements += B[i];
A1D = new double[num_of_elements] ;
for (int i=0, k=0; i<lenA; i++)
for (int j=0; j<B[i]; j++)
A1D[k++] = A2D[i][j];
for (int j=0; j<num_of_elements; j++)
std::cout << A1D[j] << std::endl;
}

std::ranges in C++20 or ranges library (C++14 compliant) does it in clean way:
double A[][4] {
{ 1, 2, 3, 4},
{ 5, 6, 7, 0},
{ 8, 9, 0, 0},
{10, 0, 0, 0}
};
for (auto x : std::ranges::views::join(A))
std::cout << x << '\n';
https://godbolt.org/z/hPP7e9

Related

Can't display the correct frequency of integers in an array

I just started with C++. The prompt is to " display the frequency of integers in the given array "
The following is the code that I have written:
#include <iostream>
#include <array>
using namespace std;
int main()
{
array <unsigned int,20> n = {1, 2, 5, 4, 3, 5, 2, 1, 3, 1, 4, 3, 3, 3, 2, 3, 3, 2, 2};
for(size_t i = 0; i < n[i]; i++)
{
int count = 0;
for(size_t j = 0; j < n.size(); j++)
{
if (n[i] == n[j])
{
count++;
}
}
cout<<"Frequency of "<<n[i]<<" is "<<count<<endl;
}
return 0;
}
But my output is :
Frequency of 1 is 3
Frequency of 2 is 5
Frequency of 5 is 2
Frequency of 4 is 2
Why isn't the frequency of 3 showing up? I am pretty sure it's a silly mistake but I can't pin point where.
Here's a simple way to count frequencies of values:
std::map<int, int> freq;
for (int const i : n)
freq[i]++; // map has the nice property that it
// defaults the value of a key to 0
for (auto const &[i, count] : freq) // this loop needs c++17
std::cout << "Frequency of " << i << " is " << count << std::endl;
Because this:
for(size_t i = 0; i < n[i]; i++)
// ^^^^
…is wrong.
You should be going up to n.size().
Currently, you're only going up to what happens to be 4 (n[4] is 3, and 4 < 3 does not hold).
This was done right for the loop over j.
As others have pointed out that there are far better ways to do this.
Such as hashing
You can read About these here: https://www.geeksforgeeks.org/counting-frequencies-of-array-elements/
Now I am gonna point out exactly where you went wrong.
in the first for loop replace i < n[i] with i<n.size()
Wrong:
for(size_t i = 0; i < n[i]; i++)
Correct :
for (size_t i = 0; i < n.size(); i++)
Your code fails as when for i=3 the value of n[i]=3 which violated your for loop condition
Here this code will run for all repetitions of a number so it will print the same results multiple times and also will do all the calculation so maintain a
A visited array that stores the no which you have already calculated.
Here is your code but Corrected
#include <iostream>
#include <array>
#include <vector>
using namespace std;
int main()
{
array<unsigned int, 20> n = {1, 2, 5, 4, 3, 5, 2, 1, 3, 1, 4, 3, 3, 3, 2, 3, 3, 2, 2};
vector<bool> visited(n.size(), false);
for (size_t i = 0; i < n.size(); i++)
{
int count = 0;
// Skip this element if already processed
if (visited[i] == true) continue;
for (size_t j = 0; j < n.size(); j++){
if (n[i] == n[j]){
count++;
// marking indexes already visited
visited[j] = true;
}
}
cout << "Frequency of " << n[i] << " is " << count << endl;
}
return 0;
}
But the best option is to learn Maps they are extremely helpful and are very easy to implement.
https://www.geeksforgeeks.org/map-associative-containers-the-c-standard-template-library-stl/
As you use std::array so i assume you are fimiliar with STL so why not use its power to solve the problem.
Find The unique elemets first from your array.
std::unordered_set<int> s(n.begin(), n.end());
Than simply use count to give count of every element in your array.
#include <algorithm>
#include <array>
#include <iostream>
#include <unordered_set>
int main()
{
std::array<unsigned int, 20> n = { 1, 2, 5, 4, 3, 5, 2, 1, 3, 1, 4, 3, 3, 3, 2, 3, 3, 2, 2 };
std::unordered_set<int> s(n.begin(), n.end());
for (const auto& itr : s) {
std::cout << "Count of "<< itr << " Is equal to = " <<std::count(n.begin(), n.end(), itr) << std::endl;
}
}

How to double values in 2d array? C++

I'm trying to double each number in 2D arrays. For example the values in array1 would become {2,4,6}{4,8,12}{6,12,18}. The problem is that my code doubles the only the first number. Can someone give me some direction on what to do?
#include <iostream>
#include <iomanip>
using namespace std;
const int N = 3;
int doubleValues(int arr[][N])
{
for (int i = 0; i < N; i++)
{
arr[i][N] *= 2;
for (int j = 0; j < N; j++)
{
arr[N][j] *= 2;
return arr[i][j];
}
}
}
void showArray(int arr[][N])
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
cout << setw(4) << arr[i][j] << " ";
}
cout << endl;
}
}
int main()
{
int array1 [N][N] = {
{ 1, 2, 3 } ,
{ 2, 4, 6 } ,
{ 3, 6, 9 }
};
int array2 [N][N] = {
{ 3, 4, 5 } ,
{ 6, 8, 10 } ,
{ 9, 12, 15 }
};
cout << "The values for array1 doubled are: \n";
doubleValues(array1);
showArray(array1);
cout << "The values for array2 double are: \n";
doubleValues(array2);
showArray(array2);
system("pause");
}
You have a return arr[i][j] in the inner loop of your doubleValues function. After doubling the first element, your function returns without doing any more work.
The solution is to remove this return statement. (And change doubleValues to a void function, because it doesn't need to return a value.)
Also, your doubleValues function seems to be modifying the wrong elements anyway. Both your accesses to arr[i][N] and arr[N][j] access elements out of bounds of your declared array size. You should probably be modifying arr[i][j] within your loop.
If you can use std::array for this project (since you know the size of your array at compile time) , you can use the functions within the <algorithm> header to easily implement your doubleValues function and not worry about hand-writing the loops.
template<typename T, std::size_t size>
void doubleValues(std::array<T,size>& arr)
{
std::transform(std::begin(arr),std::end(arr),std::begin(arr), [](auto x) { return 2 * x; });
}
This method would require that you break your 2d-array structure down into a single dimension, which can be accomplished with relative ease. For example,
std::array<int,N*N> array1 = { 1, 2, 3, 2, 4, 6, 3, 6, 9 };
std::array<int,N*N> array2 = { 3, 4, 5, 6, 8, 10, 9, 12, 15}
In the case where the size of the arrays could change dynamically, you can swap out std::array for std::vector.

Algorithm for deleting multiple array elements and shifting array

I have an array let's say with 5 items, if element[i] is less than 3 need to move element[i+1] in place of element[i].
int array[5] = {4, 2, 3, 5, 1};
int number = 3;
for (int i = 0; i < number; i++)
{
if (array[i] > number)
{
for (int j = 0; j < i - 1; j++)
{
array[j] = array[j + 1];
}
number = number - 1;
}
}
expected result is array = {2, 3, 1, anyNumber, anyNumber};
A O(n) working code for the above problem.. But as others pointed out in the comments.. You end up with an array that is using less space then allocated to it..
#include<stdio.h>
int main()
{
int arr[] = {4, 2, 3, 5, 1};
int* temp1 = arr;
int* temp2 = arr;
int i, n1 = 5, n2 = 5;
for(i = 0; i < n1; i++)
{
if(*temp2 >= 3)
{
*temp1 = *temp2;
temp1++;
temp2++;
}
else
{
n2--; //the number of elements left in the array is denoted by n2
temp2++;
}
}
}
Nested loops give you O(n2) complexity, and non-obvious code.
Better use std::remove_if:
int array[5] = {4, 2, 3, 5, 1};
int number = 3;
remove_if( begin( array ), end( array ), [=]( int x ) { return x>number; } );
Disclaimer: code untouched by compiler's hands.
Try this code. You should not decrease number at each step. Also, the second loop should start at i and stop at the end of array:
int array[5] = {4, 2, 3, 5, 1};
int number = 3;
for (int i = 0; i < number; i++)
{
if (array[i] > number)
{
for (int j = i; j < 5; j++)
{
array[j] = array[j + 1];
}
}
}
Here's a more compact and idiomatic (that's how I view it anyway) way to remove items from an array:
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
int array[] = {4, 2, 3, 5, 1};
int* begin = array;
int* end = begin + sizeof(array)/sizeof(array[0]);
int number = 3;
end = std::remove_if(begin, end, [&number](int v) {return v > number;});
std::copy(begin, end, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}
Just for comparison, here's a version using std::vector:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main()
{
std::vector<int> array = {4, 2, 3, 5, 1};
int number = 3;
auto end = std::remove_if(array.begin(), array.end(), [&number](int v) {return v > number;});
std::copy(array.begin(), end, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}
As an alternative, if you want to keep your items, but denote what will be at some later time, "removed", the algorithm that can be used is stable_partition:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <functional>
int main()
{
int vValues[] = {4,2,3,5,1};
// partition the values on left and right. The left side will have values
// <= 3, and on right >3. The return value is the partition point.
int *p = std::stable_partition(vValues, vValues + 5,
std::bind2nd(std::less_equal<int>(), 3));
// display information
std::cout << "Partition is located at vValues[" << std::distance(vValues, p) << "]\n";
std::copy(vValues, vValues + 5, std::ostream_iterator<int>(std::cout, " "));
}
Output:
Partition is located at vValues[3]
2 3 1 4 5
You will see that 2,3,1 are on the left of partition p, and 4,5 are on the right of the partition p. So the "removed" items start at where p points to. The std::partition ensures the elements are still in their relative order when done.
I created my own example, hope this helps people as a reference:
// Removing an element from the array. Thus, shifting to the left.
void remove(){
int a[] = {1, 2, 3, 4, 5, 6};
int size = sizeof(a)/sizeof(int); // gives the size
for(int i = 0; i < size; i++){
cout << "Value: " << a[i] << endl;
}
int index = 2; // desired index to be removed
for(int i = 0; i < size; i++){
if(i == index){
for(int j = i; j < size; j++){
a[j] = a[j+1];
}
}
}
size--; // decrease the size of the array
cout << "\nTesting output: " << endl;
for(int i = 0; i < size; i++){
cout << "Value: " << a[i] << endl;
}
}
int main(){
remove();
return 0;
}

Linear Search returning array with indices value is found at

I attempted a program to return an array with the indicies of the array where a specific inputed value is found, but every run results in an error, which seems to be an infinite run time. The error seems to be occuring right after printing out the last of the indicies found.
Can anyone help?
(Side note: I've seen multiple pages about deleting pointers when done with them; should I be doing that here?)
Forgot to mention - I want the first slot of the returned array to save the size of the array, so that it can be accessed easily later on in the program
#include <iostream>
#include <vector>
using namespace std;
int* linearSearch(int* n, int k, int f) {
// Input: Index 0 Address ; Size of Array; Element to Search
// Output: Array of Found Indicies
vector <int> a;
int* b;
for(int i = 0; i < k; i++)
if(n[i] == f)
a.push_back(i);
*b = a.size();
for(int i = 0; i < a.size(); i++)
b[i + 1] = a[i];
return b;
}
int main() {
int c[10] = {4, 4, 6, 3, 7, 7, 3, 6, 2, 0};
int* k = linearSearch(&c[0], sizeof(c)/sizeof(int), 4);
for(int i = 0; i < k[0]; i++) {
cout << "Found at index: " << k[i + 1] << endl;
}
return 0;
}
int* b;
....
*b = a.size();
b has to be allocated. Try following:
int* b = new int[a.size() + 1];
b[0] = a.size();
I see what you meant. b will have magically length in first element. This was in Pascal/Delphi but not the case in C/C++.
You are writing to heap memory that you never claimed.
int* b;
This pointer, having never been initialized, points to an undefined memory address. Then when you use the indexing operator to assign your matches, you are writing to the subsequent bytes following the undefined memory address.
You need to allocate space for storing the results using the 'new[]' operator. Additionally, if you had correctly claimed the memory, you would be assigning the number of match results to the first element in the result array - something that doesn't seem to be your intention.
Take a look at dynamic memory allocation in C++ using the new [] operator.
If you use std::vector anyway, why not to use it where it is needed the most? Also if you not suppose to modify array by that pointer express that by const pointer:
std::vector<int> linearSearch(const int* n, int k, int f)
{
std::vector<int> res;
for(int i = 0; i < k; i++)
if(n[i] == f) res.push_back(i);
return res;
}
int main() {
int c[10] = {4, 4, 6, 3, 7, 7, 3, 6, 2, 0};
std::vector<int> k = linearSearch(&c[0], sizeof(c)/sizeof(int), 4);
for(int i = 0; i < k.size(); i++) {
cout << "Found at index: " << k[i] << endl;
}
return 0;
}
This is not perfect but this is much closer to a correct implementation and you should be able to take it further with some work:
#include <iostream>
#include <vector>
using namespace std;
std::vector<int> linearSearch(int* n, int k, int f)
{
vector <int> a;
for(int i = 0; i < k; i++)
{
if(n[i] == f)
{
a.push_back(i);
}
}
return a ;
}
int main() {
int c[10] = {4, 4, 6, 3, 7, 7, 3, 6, 2, 0};
std::vector<int> result = linearSearch(&c[0], sizeof(c)/sizeof(int), 4);
for(unsigned int i = 0; i < result.size(); i++)
{
cout << "Found at index: " << result[i + 1] << endl;
}
return 0;
}

random shuffle operation

i have following code
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
int a[] = {2, 1, 4, 3, 5, 6, 7, 9, 8, 10, 11};
int n = sizeof(a) / sizeof(int);
int k=0;
for (int i = 0; i < n; i++)
{
k = i + rand() % (n-1-i);
int s = a[i];
a[i] = a[k];
a[k] = s;
}
for (int i = 0; i < n; i++)
{
cout << a[i] << " " << endl;
}
return 0;
}
but it gives me runtime error,i know there is a lot of method in internet ,just i choose such simple for exam preparation in university,please help me what is wrong?
I think rand()%(n-1-i) will give you a divide-by-zero for certain values if i (like i == n-1).
You might want to ask yourself what the result of %(n-1-i) will be for all possible values of i.
n = 11. When i = 10, that's a k= i+rand() % 0;
Mod by zero is undefined and can operate a number of different ways. I've seen it equivalent to mod
infinity, so it would be returning k as i+rand() which would lead to your out-of-bounds error.