get length of multidimensional array with different length in c++? - c++

I have a multidimensional array and i'm trying to get the length of each column. But it's returning 20 for all of them.
int buttons[16][5] = {{0, 4, 1},{1, 0, 2, 5},{2, 1, 3, 6},{3, 2, 7},{4,0,5,8},{5,1,4,6,9},{6,2,5,7,10},{7,3,6,11},{8,4,9,12},{9,5,8,10,13},{10,6,9,11,14},{11,7,10,15},{12,8,13},{13,9,12,14},{14,10,13,15},{15,11,14}};
sizeof(buttons[0]);

You are declaring an C-style array where each element is an array of 5 int. Therefore, with sizeof(buttons[0]), you are getting the size of 5 ints. Usually, ints have a size of 4 bytes, hence you get 20. Only apparently has buttons[0] 3 elements: in fact, in your code, you initialize only the first 3 elements of buttons[0].
If you want a multidimensional array, where each "column" has different size, you should better use std::vector which can hold array of variable size. Then size() gives you the actual number of element.
Example code:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> buttons[16] = {{0, 4, 1},{1, 0, 2, 5},{2, 1, 3, 6},{3, 2, 7},{4,0,5,8},{5,1,4,6,9},{6,2,5,7,10},{7,3,6,11},{8,4,9,12},{9,5,8,10,13},{10,6,9,11,14},{11,7,10,15},{12,8,13},{13,9,12,14},{14,10,13,15},{15,11,14}};
std::cout << buttons[0].size();
}
Even better, you could use a vector of vector:
#include <iostream>
#include <vector>
int main()
{
std::vector<std::vector<int>> buttons = {{0, 4, 1},{1, 0, 2, 5},{2, 1, 3, 6},{3, 2, 7},{4,0,5,8},{5,1,4,6,9},{6,2,5,7,10},{7,3,6,11},{8,4,9,12},{9,5,8,10,13},{10,6,9,11,14},{11,7,10,15},{12,8,13},{13,9,12,14},{14,10,13,15},{15,11,14}};
std::cout << buttons[0].size();
}

You can't do that with arrays. You can do that with vectors:
vector<vector<int> > buttons = ...;
for (auto const& button : buttons) cout << button.size() << '\n';

Related

Find the index of the n-least values in a array without sorting

I have the following array:
{7, 1, 3, 9, 5, 4, 7, 8, 2}
and a empty n-size array. Now I want to find the index of the n-least values in that given array without sorting and write them to the empty array. For example n = 3:
{1, 8, 2}
Is there an easy way to do that?
If you are not restricted in sorting other arrays, then create an array of indices and sort the array of indices in accordance with the original array.
#include <vector>
#include <iostream>
#include <algorithm>
#include <numeric>
int main()
{
int n = 3;
// test data
std::vector<int> test = { 7, 1, 3, 9, 5, 4, 7, 8, 2 };
// index array
std::vector<int> index(test.size());
// set the index array to 0, 1, 2, … n-1
std::iota(index.begin(), index.end(), 0);
// sort the index array
std::sort(index.begin(), index.end(), [&](int n1, int n2) { return test[n1] < test[n2]; });
// output results -- note we are printing the index array
for (int i = 0; i < n; ++i)
std::cout << index[i] << "\n";
}
Output:
1
8
2
Start with first value in array.
Compare the values from the array and the value of the index in the n-least array. (If empty then just add it).
If the value is less, then shift the array from that position and add the index to that position in the n-least array.
If it's not less then compare the next value from the n-least array and so forth.
This is probably not optimal but atleast it's not of O(n^2) complexity that a naive solution would yield.
I'll write this in pseudo code:
n = 3
arr = [7, 1, 3, 9, 5, 4, 7, 8, 2]
narr = []
for i as 0 to sizeof(arr) - 1
for j as 0 to n - 1
if narr[j] is undefined or arr[i] < arr[narr[j]]
narr.shiftRight(j, 1)
narr[j] = i;
break
endif
endfor
endfor

Eigen: replicate items along one dimension without useless allocations

I have some vector vec and i want to obtain a new "expression" vec2 by copying values along dimension of vector
Eigen::VectorXf vec(5);
vec << 1, 2, 3, 4, 5;
const auto vec2 = vec.someAwesomeEigenMagic<3>();
//vec2 should contains (1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5)^T
//Not (1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5)^T
Of course i can create such vector manually or by using replicate + vectorization by Eigen::Map:
MatrixXf tmp = vec.replicate(1, 3).transpose();
const Map<VectorXf> vec2(tmp.data(), vec.rows() * 3, 1);
But i want vec2 to be some kind of "eigen template expression" without allication (vec can be quite big and i will call this routine quite often) and immediate computing of values. (vec contains per vertex weights and i want to use it for weighted least squares)
I thought about kronecker product trick with vector of ones, but i'm not sure is it optimized for product by ones. Also i prefer to avoid unsupported module
PS Sorry for my English
Using the devel branch you can use LinSpaced to generate the sequence of indices and then index the input vector:
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
int main()
{
VectorXf vec(5);
vec << 1, 2, 3, 4, 5;
auto vecrep = vec(ArrayXi::LinSpaced(5*3,0,4));
cout << vecrep.transpose() << endl;
}
you can then wrap the key line within a free function returning auto, in c++14:
template<typename XprType>
auto magic_rep(const XprType &xpr, Index K) {
return xpr(Eigen::ArrayXi::LinSpaced(xpr.size()*K,0,xpr.size()-1));
}
and in main:
cout << magic_rep(vec,3).transpose() << endl;

Standard library function to create array of indices whose corresponding value is a given number

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

Are duplicates of the nth element always contiguous when using std::nth_element?

vector<int> data = {3, 1, 5, 3, 3, 8, 7, 3, 2};
std::nth_element(data.begin(), data.begin() + median, data.end());
Will this always result in:
data = {less, less, 3, 3, 3, 3, larger, larger, larger} ?
Or would a other possible outcome be:
data = {3, less, less, 3, 3, 3, larger, larger, larger} ?
I've tried it multiple times on my machine wich resulted in the nth values always being contiguous. But that's not proof ;).
What it's for:
I want to building a unique Kdtree but I have duplicates in my vector. Currently I'm using nth_element to find the median value. The issue is to select a unique/reconstructible median, without having to traverse the vector again. If the median values were contiguous I could choose a unique median, without much traversing.
No. The documentation does not specify such behavior, and with a few minutes of experimentation, it was pretty easy to find a test case where the dupes weren't contiguous on ideone:
#include <iostream>
#include <algorithm>
int main() {
int a[] = {2, 1, 2, 3, 4};
std::nth_element(a, a+2, a+5);
std::cout << a[1];
return 0;
}
Output:
1
If the dupes were contiguous, that output would have been 2.
I have just tried several not-so-simple examples, and on the third got non-contiguous output.
Program
#include <vector>
#include <iostream>
#include <algorithm>
int main() {
std::vector<int> a = {1, 3, 3, 2, 1, 3, 5, 5, 5, 5};
std::nth_element(a.begin(), a.begin() + 5, a.end());
for(auto v: a) std::cout << v << " ";
std::cout << std::endl;
}
with gcc 4.8.1 under Linux, with std=c++11, gives me output
3 1 1 2 3 3 5 5 5 5
while the n-th element is 3.
So no, the elements are not always contiguous.
I also think that even a simpler way, with no thinking of a good test case, was just generating long random arrays with many duplicate elements and checking whether it holds. I think it will break on the first or second attempt.

C++, Sorting Separate Arrays Simultaneously [duplicate]

This question already has answers here:
Sorting zipped (locked) containers in C++ using boost or the STL
(5 answers)
Closed 8 years ago.
Consider the case where “rowPtr”, “colInd” and “values” in a struct are dynamically allocated with same number of elements. In this scenario, what is the fastest way (without copying if possible!!) to sort elements of colInd so that rowPtr and value elements are swapped or change positions based on how elements of colInd change positions.
struct csr
{
int rows;
int cols;
int nzmax;
int *rowPtr;
int *colInd;
double *values;
};
// A simple example without a struct. Just based on arrays
double values[10] = {0.2135, 0.8648, 7, 0.3446, 0.1429, 6, 0.02311, 0.3599, 0.0866, 8 };
int rowPtr[10] = { 0, 3, 6, 10, 2 -1, 24, -4, 1, 11 };
int colInd[10] = { 0, 2, 4, 1, 2, 3, 0, 1, 2, 4 };
// sort colInd and simultaneously change positions in rowPtr and values
//After sorting
Values = {0.214, 0.023, 0.345, 0.360, 0.865, 0.143, 0.087, 6.0};
rowPtr = {0, 24, 10, -4, 3, 2, 1, -1};
colInd = {0, 0, 1, 1, 2, 2, 2, 3};
I suggest putting the three arrays into an array of struct and sorting the array of struct.
struct csr_data
{
int rowPtr;
int colInd;
double value;
};
and
struct csr
{
int rows;
int cols;
int nzmax;
csr_data* data_array;
};
You can sort an array of csr_data using any of the three member variables. When they are sorted, all elements of csr_data will be rearranged regardless of which member you use to sort the data by.