I am working on a program which takes the initial array as an input and then randomly generates 10 random arrays from the initial array.
I have written a function to generate a single random array from the initial array.
However,I am unable to develop a code which calls this function in the main function and generates 10 such random arrays.I will also be using these 10 randomly generated arrays for further calculation in the main function.
Since my knowledge of C++ is limited for now,I am not aware of using vectors for dynamic allocation.It would be of great help if anyone can guide be regarding the code to be used in the main function.
Here int initial[] is the first array used to generate 10 other random arrays using the int *newparents() function. When the newparents() function is called in main it returns one randomly shuffled array.
I would request your help in generating 10 random arrays in the main function by calling the newparents() function and then storing them for further use.
Code :
int initial[] =
{ 10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200 };
int size = sizeof(initial) / sizeof(initial[0]);
int *newparents()
{
int *pt = new int[size];
random_shuffle(&initial[0], &initial[size]);
for (unsigned i = 0; i<size; i++)
{
pt[i] = initial[i];
}
return pt;
}
int main()
{
int *p;
p = newparents();
cout << "p1=" << " ";
for (int i = 0; i<size; i++)
{
cout << *(p + i) << " ";
}
return 0;
}
Thank you for your help.
A simple way to do this using std::vector :
#include <iostream>
#include <vector>
#include <algorithm>
std::vector< std::vector<int> >
GenerateRandomArrays( std::vector<int> const & inInitialArray, int inNumberOfArrays)
{
std::vector<std::vector<int> > generatedArrays;
std::vector<int> tempArray(inInitialArray);
for (int i = 0; i < inNumberOfArrays; i++)
{
std::random_shuffle(tempArray.begin(), tempArray.end());
generatedArrays.push_back(tempArray);
}
return generatedArrays;
}
int main() {
// Creates the initial array.
std::vector<int> initial{ 10,20,30,40,50 };
auto blah = GenerateRandomArrays(initial, 10);
return 0;
}
Output :
50 20 40 30 10
50 40 30 10 20
20 10 30 50 40
30 40 20 10 50
30 50 20 10 40
20 50 10 40 30
50 30 20 10 40
30 40 20 10 50
20 10 50 40 30
20 50 10 40 30
Note : I am creating a new tempArray only because I think you do not want to alter the intial vector. If that is not a case for you then, you can just shuffle the initial array itself and add it to the vector of vectors.
To create array of 10 pointers to the shuffled arrays using your code you can simply:
int *arr[10];
for (int i = 0; i < 10; ++i)
arr[i] = newparents();
int *arr[10]; will create array of 10 pointers to int, which is what what your newparents(); function returns, a pointer to the first int of shuffled array.
Since you allocated those arrays on the heap, make sure you free that memory once finished with them:
for (int i = 0; i < 10; ++i)
delete[] arr[i];
I have written a function to generate a single random array from the initial array.
No, you wrote a function to shuffle the initial array in place and then copy it. This is frankly a bit odd, because I don't see why you want to mutate the global in-place (after the first time you call your function, the global array is still called "initial" but is no longer in its initial state).
Since my knowledge of C++ is limited for now,I am not aware of using vectors for dynamic allocation.
The whole point is that std::vector handles all the allocation for you, avoiding the memory leaks and manual copying in your current code.
If you take the time to use C++ properly, instead of trying to write C in C++, the code is pretty trivial:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
// let's avoid mutating our global state
const std::vector<int> Seeds =
{10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200};
// this shuffles a copy of the argument passed
std::vector<int> shuffle(std::vector<int> v) {
std::random_shuffle(begin(v), end(v));
return v;
}
// return n independently-shuffled copies of "initial"
std::vector<std::vector<int>> shuffle_n(size_t n,
std::vector<int> const& initial) {
std::vector<std::vector<int>> result(n);
std::generate_n(begin(result), n,
[&initial]() {
return shuffle(initial);
});
return result;
}
int main() {
// one line to create 10 shuffled vectors
auto allparents = shuffle_n(10, Seeds);
// and one loop to print them all
for (auto &v : allparents) {
std::cout << '{';
std::copy(begin(v), end(v),
std::ostream_iterator<int>(std::cout, " "));
std::cout << "}\n";
}
}
Related
#include <stdio.h>
#include <vector>
using namespace std;
int main()
{
vector<int> numbers;
numbers.resize(10001);
for (int i = 0; i < 10000; i++)
{
numbers.push_back(1);
}
return 0;
}
If I put more than 5000 1s in the vector, I get the following error, I don't understand.
There is no doubt about it other than the memory overflow. But int type = 4 bytes, so 4byte * 10000 = 40000byte 0.04mb
Why am I getting an error?
The error seems unrelated to the code that you've shown.
Now, looking at your code there is no need to use resize and then using push_back as you can directly create a vector of size 10001 with elements initialized to 1 as shown below:
std::vector<int> numbers(10001,1);// create vector of size 10001 with elements initialized to 1
Or you can used std::vector::reserve instead of std::vector::resize, though this is totally unnecessary as you can use the first method shown above.
vector<int> numbers;
numbers.reserve(10001); //use reserve instead of resize
for (int i = 0; i < 10000; i++)
{
numbers.push_back(1);
}
Suppose I created an array of size 5. Filled two number 1 and 2 at index 0 and 1 respectively. Now I want to return number of elements currently present in the array, i.e. 2 and not 5 given by size below. How can I do that?
int arr[5];
arr[0] = 1;
arr[1] = 2;
//size returns 5 but I want it to return 2, since it has only 2 elements.
int size = sizeof(arr)/sizeof(arr[0]);
cout << size;
If you use a classic array, it is not possible to do what you say, you will get 5 outputs each time. But if you use std::vector, the size of the vector will change automatically every time you add a new element to the vector. Then, you can easily count the number of elements in the vector by using the size() function. you can print to the screen.
#include<iostream>
#include<vector>
int main() {
std::vector<int> vec;
for (size_t i = 1; i <= 2; ++i) { vec.push_back(i); }
std::cout << "number of elements= " << vec.size();
return 0;
}
While taking a look at a solution for a problem, I came across this implementation of a vector.
const int MX = 100000;
std::vector <int> adj[MX];
The push_back() function doesn't work with this implementation of the vector class, and to add an element, the following code was used:
std::ifstream fin ("file.in");
int N = 5;
for (int i = 0; i < (N-1); i++) {
int A,B; fin >> A >> B; // reading values from another file
adj[A].pb(B), adj[B].pb(A);
}
The way this code is adding is adding pushing back a value to a certain part of the list, which I imagine as a vector inside the vector of the form:
{
{ },
{ }
}
In addition, how would I loop through this vector because for (int n : adj) does not work. I am not sure what the form of this vector is because this method of looping does not work.
What you have is C style array of vectors, off the bat you could replace that with std::array:
std::array<std::vector<int>, MX> adj;
To loop through these you would have to use a nested one, the outer loop to go through the array, and the inner one to go through each vector, something like this:
const int MX = 3;
//array of 3 vectors
std::array<std::vector<int>, MX> adj {{{1,2,3,4}, {5,6,7,8}, {9, 10, 11, 12}}};
for(auto &v : adj){ //for the array
for(auto i : v){ //for each vector
std::cout << i << " ";
}
std::cout << "\n";
}
Output:
1 2 3 4
5 6 7 8
9 10 11 12
You can also access individual elements using C style indexing:
std::cout << adj[1][0]; // vector element index 0 of array index 1
Or in a safer way, using container member at:
std::cout << adj.at(1).at(0);
This would output 5.
You should be careful though, when randomly filling the array, an array is not meant to have empty elements, otherwise the loops will go through uninitialized array members, which is not ideal, perhaps you are looking for some other kind of container.
I found the same question for PHP and I tried to do the same in C++.
I tried following:
// returns new array with numbers lower then "number", len is set to
// new length.
int * filter(int array[], int &len, int number) {
int cnt = 0;
for (int i = 0; i < len; i++) {
if (array[i] < number) {
cnt++;
}
}
int *ret = new int[cnt];
cnt = 0;
for (int i = 0; i < len; i++) {
if (array[i] < number) {
ret[cnt] = array[i];
cnt++;
}
}
len = cnt;
return ret;
}
This function will create a new array with the integers that are lower than the integer number. I tried to bypass the problem that I don't know how long the new array should be.
Is there any better way to solve this problem?
Yes, use std::vector type. It will automatically handles allocations for you each time you push value to it (using push_back method).
Example
#include <iostream>
#include <vector>
int main() {
std::vector<int> a;
a.push_back(1);
a.push_back(2);
for (int value : a) {
std::cout << value << '\n';
}
}
It's also a good idea to avoid new syntax, as it doesn't automatically deallocate, unlike std::vector.
Also, while this is unrelated to question, C++ provides a function that does what you want already called std::copy_if.
std::remove is the algorithm you're looking for.
#include <iterator>
#include <algorithm>
int main()
{
int array[4] = {1, 42, 314, 42};
// If you only know `array` as a pointer, and `len`, then
// `std::begin(array)` becomes `array`, and
// `std::end(array)` becomes `array + len`.
auto end = std::remove(std::begin(array), std::end(array), 42);
// Now `end` points to the "new end" of the array.
// And `std::distance(std::begin(array), end)` is the "new length".
}
It moves all matched elements (42 in the example) to the end of the array. When inspecting array after std::remove runs, you get {1, 314, 42, 42}, and end points past the last nonmatching element (the first 42 in this case).
It's also possible to copy the nonmatching elements to another array using std::remove_copy, or std::copy_if, but in order to do this, you'll have to allocate another array of elements. At this point, you're better off using a dynamic growing array such as std::vector. In that case, use std::vector::erase like here in the answers with std::remove.
I was trying to dig more into using arrays and pointers while I came across this problem:
main.cpp:13:7: error: cannot convert 'int [2][5][10]' to 'int*'
in assignment show=ary;
Here's the code:
#include <iostream>
using namespace std;
void arrayLearn(int *);
int main()
{
int ary[2][5][10];
int *show;
ary[2][4][9]=263;
ary[2][5][10]=100;
show=ary; //line 13
arrayLearn(show); //line 14
cout <<"End process"<<endl;
return 0;
}
void arrayLearn(int *arg)
{
for(int i=0;i<100;i++)
{
cout<<"Pointer position: "<<i<<" Value: "<<*(arg++)<<endl;
}
}
If I remove the line 13 and replace line 14 with the following code,
arrayLearn(ary[5][10]);
then the program compiles, but I don't understand why I should pass only two dimensions and not three. If I'm passing the pointer to the first item in the array then why can't I just pass the pointer like this?
arrayLearn(ary);
Please let me know if I've missed some vital concepts or failed to see a really simple mistake.
As Abhishek stated, you are trying to pass a 3-dimensional array to a 1-dimensional object.
If the show variable is not used anywhere else, you can do the following:
#include <iostream>
using namespace std;
void arrayLearn(int *);
int main()
{
int ary[2][5][10];
// Code change explained below (see Note)
ary[1][4][8] = 263;
ary[1][4][9] = 100;
// Pass the starting address of the array
arrayLearn(&ary[0][0][0]);
cout <<"End process"<<endl;
return 0;
}
// Iterate through the array using the position of the elements in memory
void arrayLearn(int *arg)
{
for(int i=0;i<=100;i++)
{
cout<<"Pointer position: "<<i<<" Value: "<<*(arg++)<<endl;
}
}
Output:
...
Pointer position: 98 value: 263
Pointer position: 99 value: 100
End process
This way allows you to pass the starting address of the array to the function.
Note: It should be noted that your original array assignments ary[2][4][9] = 263; and ary[2][5][10] = 100; are outside the bounds of the array. Array indexes start at 0. So even though you have declared your array as ary[2][5][10]; To access the last array element, you would use ary[1][4][9];.
If you are willing to use std::vector, which I highly recommend, you can use the following code to create a 2D vector:
using std::vector<int> Vec1;
using std::vector<Vec1> Vec2;
using std::vector<Vec2> Vec3;
Vec3 a(2, Vec2(5, Vec1(10, 0));
and then change the argument of arrayLearn to const Vec3& to call it using a.
void arrayLearn(const Vec3& arg)
{
// You'll need to use three loops to traverse all the elements.
for ( auto const& v2 : arg )
{
for ( auto const& v1 : v2 )
{
for ( auto const& item : v1 )
{
// Use item
}
}
}
}
In simple terms, ary is 3-Dimensional and show is 1-Dimensional. The compilation errors tell you that you can't convert 3D into 1D. Now, why does following work?
arrayLearn(ary[5][10]);
It is because, ary[5][10] is referring to 1D (a row or a column or a height, depends on how you visualize 3D array) and arrayLearn is also accepting 1D parameter.
if you want to pass ary using show then pass 2D like ary[5][10] to show variable, something like following :)
show = ary[5][10];
you can use STL data structurs like vector, map , linkedlist , ...
that all of them are better that array both in emplementation and in performance.
but for solving exactly this problem, you must pass 3 dimention array to one function in this manner:
int array[10][7][8];
void function_sample(int (*a)[7][8] , int length)
{
//for example for printing array cells
for(int i =0 ; i< length ; i++)
{
for(int j =0 ; j< 7 ; j++)
{
for(int k =0 ; k< 8 ; k++)
{
cout << a[i][j][k] << endl
}
}
}
//....
}
and for calling this function :
int array[10][7][8] //= {initial your array};
function_sample(array , 10);