I'm trying to rewrite code I've written in matlab in C++ instead.
I have a long cell in matlab containing 256 terms where every term is a 2x2 matrix. In matlab i wrote it like this.
xA = cell(1,256);
xA{1}=[0 0;3 1];
xA{2}=[0 0;13 1];
xA{3}=[0 0;3 2];
and so on...
What would be the easiest thing to use in c++?
Can I give an array with the dimensions [256][2][2] all the 4 values at a time or do I have to write one line for every specific valuen in the array?
/Mr.Buxley
You can certainly initialize them all at once, although it sounds like a lot of tedious typing:
float terms[256][4] = {
{ 0, 0, 3, 1 },
{ 0, 0, 13, 1 },
{ 0, 0, 3, 2}
...
};
I simplified it down to an array of 256 4-element arrays, for simplicity. If you wanted to really express the intended nesting, which of course is nice, you need to do:
float terms[256][2][2] = {
{ { 0, 0 }, { 3, 1 } },
{ { 0, 0 }, { 13, 1 } },
{ { 0, 0 }, { 3, 2 }}
...
};
That would be 256 lines, each of which has a "list" of two "lists" of floats. Each list needs braces. But, since C++ supports suppressing braces in things like these, you could also do:
float terms[256][2][2] = {
{ 0, 0, 3, 1 },
{ 0, 0, 13, 1 },
{ 0, 0, 3, 2}
...
};
In fact, you could even remove the braces on each line, they're optional too. I consider relying on the suppression slightly shady, though.
If you want to use higher-level types than a nested array of float (such as a Matrix<2,2> type, or something), initialization might become tricker.
Related
I am working on a problem in C++ that involves calculations on arrays of objects sorted along different attributes. Suppose I have an array of 5 objects with 3 different attributes (A, B, and C), and I sort the array according to each attribute individually. This gives me three arrays that tell me for each object where its position would be if I were to sort them along the corresponding attribute.
std::vector<int> A_Order = { 1, 3, 0, 2, 4 };
std::vector<int> B_Order = { 2, 4, 3, 1, 0 };
std::vector<int> C_Order = { 0, 2, 4, 3, 1 };
Now I want to split the objects into 2 subsets, always picking a position N in one of the orderings, where all objects at position x <= N go into the first subset, and all x > N go into the next subset. If I do this on attribute A at N = 2, I get the following:
std::vector<int> A_OrderSub0 = { 1, 0, 2 };
std::vector<int> B_OrderSub0 = { 2, 3, 1 };
std::vector<int> C_OrderSub0 = { 0, 4, 3 };
std::vector<int> A_OrderSub1 = { 3, 4 };
std::vector<int> B_OrderSub1 = { 4, 0 };
std::vector<int> C_OrderSub1 = { 2, 1 };
To perform the next iteration of calculations efficiently, I once again need the subsets to be ordered along the attributes and get the resulting positions (in the example above, I need B_OrderSub1 = { 4, 0 } to become B_OrderSub1 = { 1, 0 }). What is the most efficient way for me to reuse the "global positions", which I only have to get once at the start, to then get the "locally ordered positions" for the objects each time I split them into subsets?
I am trying to store a cell-like structure in C++, where its elements can have arrays of different lengths like the following example:
myMultiSizedArray = {
{ 1, 2, 4 },
{ 3, 5, 6, 7 },
{ 7, 8, 9, 10 },
{ 1, 3 },
{ 4, 5, 8 },
{ 9, 10 }
{ 5 } }
I am thinking of using a vector in a struct such as the following:
struct f
{
std::vector<int> elements;
};
std::vector<f> myMultiSizedArray;
I would appreciate it if the community could give me their feedback. Are there better, more efficient approaches? Does C++ provide a means for this? Thank you
As mentioned by other users as comment, you could use a vector inside another vector as in piece of code below:
using namespace std;
vector<vector<int>> myMultiSizedArray;
myMultiSizedArray.push_back({ 1, 2, 3, 4 });
myMultiSizedArray.push_back({ 6, 5, 200, 3, 2, 1 });
use "vector< vector< int > >" is better
I have a function declaration as follows
void set_values(float values[4][4]);
If I call the function like this everything is OK.
float values[4][4] = {
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 }
};
mat1.set_values(values);
However i thought that I could take the array declared in the curly braces and pass it directly into the function like this:
mat1.set_values({
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 }
});
But this gives me a compile error too many initializer values
Why does the first code work but not the second one?
Your function expects an array object, not an initialization list for such an object.
I've got a C-style array called board that contains some char's. I'm trying to create a std::array or std::vector (either would be fine, although std::array would be preferable) to store all the indices of board that are a certain value (in my case, 0).
This code I wrote is functional and works well:
std::vector<int> zeroes;
zeroes.reserve(16);
//board has 16 elements, so zeroes.size() will never be larger than 16.
//I used this reserve for speedup - the compiler doesn't require it.
for (int i = 0; i < 16; ++i)
{
if (board[i] == 0)
{
zeroes.push_back(i);
}
}
However, from past experience, whenever a std function exists that could replace part of my code, it is terser and hence stylistically preferred and also faster. My function seems like a fairly basic operation - I know there is a standard function* to access the index of an array that contains a value when that value only occurs once** in the array. So, is there a standard function to create an array of the indices that contain a value, assuming that more than one such index exists?
* Technically, two nested function calls: int x = std::distance(board, std::find(board, board + 16, 0));. See the accepted answer here.
** Well, it still works if more than one index with the desired value is present, but it returns only the first such index, which isn't very useful in my context.
Edit:
As one of the answers misunderstood the question, I'll clarify what I'm seeking. Let's say we have:
char board[16] = {0, 2, 0, 4,
2, 4, 8, 2,
0, 0, 8, 4,
2, 0, 0, 2};
Now, the indices which I'm looking for are {0, 2, 8, 9, 13, 14} because board[0] = 0, board[2] = 0, board[8] = 0, etc. and these are the only numbers which satisfy that property.
Here's a solution using std::iota and std::remove_if:
#include <algorithm>
#include <iostream>
int main () {
const std::size_t board_size = 16;
char board [board_size] = {
0, 2, 0, 4,
2, 4, 8, 2,
0, 0, 8, 4,
2, 0, 0, 2
};
// Initialize a zero-filled vector of the appropriate size.
std::vector<int> zeroes(board_size);
// Fill the vector with index values (0 through board_size - 1).
std::iota(zeroes.begin(), zeroes.end(), 0);
// Remove the index values that do not correspond to zero elements in the board.
zeroes.erase(std::remove_if(zeroes.begin(), zeroes.end(), [&board] (int i) {
return board[i] != 0;
}), zeroes.end());
// Output the resulting contents of the vector.
for (int i : zeroes) {
std::cout << i << std::endl;
}
}
Output of the program (demo):
0
2
8
9
13
14
I have the following matrix:
unsigned wins[8][3] = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }, { 0, 3, 6 }, { 1, 4, 7 }, { 2, 5, 8 }, { 0, 4, 8 }, { 2, 4, 6 } };
how to convert it into a std::vector?
You can use the two iterator constructor to instantiate a vector with a copy of of the data in wins:
unsigned* start = &wins[0][0];
std::vector<unsigned> vwins(start, start + (8 * 3));
This relies on pointer arithmetic, the fact that pointers are iterators, and the fact that 2D arrays are contiguous blocks, essentially 1D arrays with clever indexing.
Since I don't know whether you want a 2D vector or not, I'll handle the 2D case since juanchopanza handled the 1D case. :) If you're using C++11, then you can just do this:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<vector<int>> wins = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }, { 0, 3, 6 }, { 1, 4, 7 }, { 2, 5, 8 }, { 0, 4, 8 }, { 2, 4, 6 } };
for(vector<int> & row : wins) {
for(int &col : row) {
cout << col << " ";
}
cout << endl;
}
return 0;
}
This example uses C++11 initializer lists to create an analogous structure, also called wins. I also wrote a little code to show how you could loop through it to print it out in a sensical order.
Hope this helps! :)