Shifting elements in array by N elements - c++

I have an array where each 'element' is composed of 4 consecutive values. Upon update I move the array by 4 values towards the end and insert 4 new values in the beginning.
Shift:
int m = 4;
for (int i = _vsize - 1; i + 1 - m != 0; i--){
_varray[i] = std::move(_varray[i - m]);
}
Insertion:
memcpy(&_varray[0], glm::value_ptr(new_element), 4 * sizeof(float));
where new_element is of type glm::vec4 containing said 4 new values.
Any suggestions on how to improve this?
(Right now Im only shifting by one element, but want the flexibility of being able to shift say 8 times, without having to put this in a loop)
Thank you.

You can try std::copy_backward. You want to copy a range of values to another range in the same container. Since the ranges overlap and you are copying to the right you can't use regular std::copy but must use std::copy_backward instead.
int m = 4; // make this a multiple of your 'element' size
std::copy_backward(&_varray[0], &_varray[_vsize - m], &_varray[_vsize]);
There is also std::move_backward but that doesn't really matter since your float values aren't movable.

Related

Efficiently inserting column/row into a matrix stored in row/col-major vector in-place

It's not hard to efficiently insert row or column into a matrix stored in a row-
or col-major (respectively) vector. The problem of inserting row into a col-major vector or column into a row-major vector is slightly more interesting.
For example, given a 2x3 matrix stored in row-major in vector:
1 2 3 <=> 1 2 3 4 5 6
4 5 6
and a column 7 8 that is inserted before after column 1 in the original matrix, we get:
1 7 2 3 <=> 1 7 2 3 4 8 5 6
4 8 5 6
[Inserting a row into a col-major vector is similar.]
The sample setup in C++:
auto m = 2; // #rows
auto n = 3; // #cols
// row-major vector
auto x = std::vector<double>{1,2,3,4,5,6};
auto const colIndex = 1;
auto const col = std::vector<double>{7,8};
// insert column {7,8} into the 2nd position
// =>{1,7,2,3,4,8,5,6}
There could be various options to achieve this algorithmically and in C++, but we're looking for the efficiency and scalability to large matrices and multiple inserts.
The first obvious option that I can think of is to use std::vector<double>::insert to insert new elements to the correct positions:
//option 1: insert in-place
x.reserve(m*(n+1));
for(auto i = 0; i < col.size(); i++)
x.insert(begin(x) + colIndex + i * (n + 1), col[i]);
, which is valid but extremely slow even for moderate data sizes because of the resizing and shifting on each iteration.
Another, more direct option is to create another vector, populate all the columns in the ranges [0,colIndex),colIndex,(colIndex,n+1], and swap it with the original vector:
// option 2: temp vec and swap
{
auto tmp = std::vector<double>(m*(n+1));
for(auto i = 0; i < m; i++)
{
for(auto j = 0; j < colIndex; j++)
tmp[j + i * (n + 1)] = x[j + i * n];
tmp[colIndex + i * (n + 1)] = col[i];
for(auto j = colIndex + 1; j < n + 1; j++)
tmp[j + i * (n + 1)] = x[(j - 1) + i * n];
}
std::swap(tmp, x);
};
This is much faster than the option 1, but requires extra space for the matrix copy and iterating over all elements.
Are there any other ways to achieve this that would beat the above in speed/space or both?
Example code on ideone: https://ideone.com/iXrPfF
This version is likely to be much faster, especially at scale, and could be the basis for further micro-optimization (if [and only if] really necessary):
// one-time reallocation of the vector to get space for the new column
x.resize(x.size() + col.size());
// we'll start shifting elements over from the right
double *from = &x[m * n];
const double *src = &col[m];
double *to = from + m;
size_t R = n - colIndex; // number of cols left of the insert
size_t L = colIndex; // number of cols right of the insert
while (to != &x[0]) {
for (size_t i = 0; i < R; ++i) *(--to) = *(--from);
*(--to) = *(--src); // insert value from new column
for (size_t i = 0; i < L; ++i) *(--to) = *(--from);
}
ideone
This doesn't require any temporary allocation and aside from possible micro-optimizations of the loop it's probably about as fast as it gets. To understand how it works, we can start by observing that the bottom-right element of the original matrix is being shifted m elements to the right in the source vector. Working backwards from the last element, at some point a value from the inserted column vector gets inserted, and subsequent elements from the source vector are now shifted m - 1 only elements to the right. Using that logic we simply construct a 3-phase loop that works from right to left on the source array. The loop iterates m times, once for each row. The three phases of the loop, corresponding to its three lines of code, are:
Shift row elements that are "to the right" of the insertion point.
Insert the row value from the new column.
Shift row elements that are "to the left" of the insertion point (shifting one less place than in phase 1).
There's also serious room for improvement in the naming of the variables, and the algorithm should certainly be encapsulated in its own function with proper input parameters. One possible signature would be:
void insert_column(std::vector<double>& matrix,
size_t rows, size_t columns, size_t insertBefore,
const std::vector<double>& column);
From here there's further room for improvement in making it generic using templates.
And from there, you might observe that the algorithm has possible application beyond matrices. What's really happening is that you're "zippering" two vectors together with a skip and an offset (i.e., starting at element i, insert an element from B into A after every n'th element).
so what I would go with is something like (completely untested (tm))
x.resize(x.size() + col.size());
for (size_t processed = 0; processed < col.size(); ++processed) {
// shift the elements for row n (starting at the end)
// to their new location
auto start = x.end()-(processed+1) * rowSize;
auto end = start + rowSize;
auto middle = end - (col.size()-processed);
std::rotate(start, middle, end);
// replace one of the default value items to be the new value
x[x.size()- rowSize*(1+processed)] = col[col.size()-processed-1];
}
The idea being that you go from
[1,2,3,4,5,6] & adding [a,b,c]
Resize:
[1,2,3,4,5,6,x,x,x]
First loop shift:
[1,2,3,4,x,x,x,5,6]
First loop replace
[1,2,3,4,x,x,c,5,6]
Second loop shift
[1,2,x,x,3,4,c,5,6]
and so on.
Since std::rotate is linear, and each item only ever gets moved once; this should also be linear.
This differs to your option #1 in that every time you inserted, you have to move everything afterwards; meaning that the last x elements are shifted col.size() times.
An alternate solution can be transpose followed by insertion and transpose again. However, the in-place transpose in non-trivial (https://en.wikipedia.org/wiki/In-place_matrix_transposition). See the implementation here https://stackoverflow.com/a/9320349

C++ : Fastest Way to find number of elements of one array in another array

I have two arrays, one sorted array int b[] and other unsorted array int a[n] having n elements . The sorted array is made of some or all elements of unsorted array. Now there are M queries. For each query values of l and r are given. In each query I need to find the number of elements of a[n] which are present in b[].
For eg -
N=5 ,M=2
a= [2 5 1 2 3]
b=[3 2 1]
for each m:
l=1 r=5 ->a[1]=1, a[5]=5 -> answer should be 3 as all elements of b i.e 1,2,3 are present in a
l=2 r=4 ->a[2]=5 , a[4]=2 ->answer should be 2 as only 1 and 2 are there in b for given value of l and r for array.
How to find the answer with not more than O(M * LOGN) time complexity ?
NOTE:
Array is not necessary. Vector can also be used that is if it helps in reducing time complexity or easier to implement the code.
Well i think you can do something like this
std::map<int,int> c;
for(int i = 0;i<b.length.i++){
c[b[i]] = 0;
}
for(int i = l; i<=r; i++){
int number = a[i];
c[number]++;
}
//Iterate through c with b index and get all number which different than 0. The left is for you
The purpose of this is creating a map hold index of B. Then while iterating A you can increase the c value. So that after that you can check whether each element in C has value different than zero mean that A has hold the number of B.
You can use array instead of map if C starting from zero and increase by 1 for better performance. Make sure to check if a[i] can throw out of bounds exception if you use array.

What is being referenced for this matrix?

I was given the following code to use as part of an exercise. I am instructed to create a 3x3 matrix and assign specific values to it.
Here is the code:
void minput(int* m, int row, int col) {
/* assign 3X3 matrix to following value
8 1 6
3 5 7
4 9 2
*/
*(m+0) = 8;
}
What I am trying to figure out is what this piece of code *(m+0) = 8; is for. I know that adding a * in front of any variable means to "give me whatever is that the address".
What does the +0 do?
*(m+0) is equivalent to m[0]. So the whole statement is assigning 8 to m[0].
it dereferences m (gives you the value at it) I'm guessing it's + 0 so that you can add in different values and get the resulting part of the matrix
Arrays are contiguous in memory, so if you were to add 1 instead of 0, you would set the next value in the matrix to 8.
*(m+0) = 8 is the same as m[0] = 8, it dereferences the pointer to the first element then assigns to it the value 8. In your code you represent the matrix via a one-dimensional array, so you probably want to index your (i,j) component as
m+i*col + j or, equivalently, m[i*col+j], i.e. the line
*(m+i*col+j) = x // can also write is as m[i*col+j] = x
assigns x to the (i,j) component.

I don't understand how to create and use dynamic arrays in C++

Okay so I have;
int grid_x = 5
int * grid;
grid = new int[grid_x];
*grid = 34;
cout << grid[0];
Should line 3 create an array with 5 elements? Or fill the first element with the number 5?
Line 4 fills the first element, how do I fill the rest?
Without line 4, line 5 reads "-842150451".
I don't understand what is going on, I'm trying to create a 2 dimensional array using x and y values specified by the user, and then fill each element one by one with numeric values also specified by the user. My above code was an attempt to try it out with a 1 dimensional array first.
The default C++ way of creating a dynamic(ally resizable) array of int is:
std::vector<int> grid;
Don't play around with unsafe pointers and manual dynamic allocation when the standard library already encapsulates this for you.
To create a vector of 5 elements, do this:
std::vector<int> grid(5);
You can then access its individual elements using []:
grid[0] = 34;
grid[1] = 42;
You can add new elements to the back:
// grid.size() is 5
grid.push_back(-42);
// grid.size() now returns 6
Consult reference docs to see all operations available on std::vector.
Should line 3 create an array with 5 elements?
Yes. It won't initialise them though, which is why you see a weird value.
Or fill the first element with the number 5?
new int(grid_x), with round brackets, would create a single object, not an array, and specify the initial value.
There's no way to allocate an array with new and initialise them with a (non-zero) value. You'll have to assign the values after allocation.
Line 4 fills the first element, how do I fill the rest?
You can use the subscript operator [] to access elements:
grid[0] = 34; // Equivalent to: *(grid) = 34
grid[1] = 42; // Equivalent to: *(grid+1) = 42
// ...
grid[4] = 77; // That's the last one: 5 elements from 0 to 4.
However, you usually don't want to juggle raw pointers like this; the burden of having to delete[] the array when you've finished with it can be difficult to fulfill. Instead, use the standard library. Here's one way to make a two-dimensional grid:
#include <vector>
std::vector<std::vector<int>> grid(grid_x, std::vector<int>(grid_y));
grid[x][y] = 42; // for any x is between 0 and grid_x-1, y between 0 and grid_y-1
Or might be more efficient to use a single contiguous array; you'll need your own little functions to access that as a two-dimenionsal grid. Something like this might be a good starting point:
template <typename T>
class Grid {
public:
Grid(size_t x, size_t y) : size_x(x), size_y(y), v(x*y) {}
T & operator()(size_t x, size_t y) {return v[y*size_x + x];}
T const & operator()(size_t x, size_t y) const {return v[y*size_x + x];}
private:
size_t size_x, size_y;
std::vector<T> v;
};
Grid grid(grid_x,grid_y);
grid(x,y) = 42;
Should line 3 create an array with 5 elements? Or fill the first element with the number 5?
Create an array with 5 elements.
Line 4 fills the first element, how do I fill the rest?
grid[n] = x;
Where n is the index of the element you want to set and x is the value.
Line 3 allocates memory for 5 integers side by side in memory so that they can be accessed and modified by...
The bracket operator, x[y] is exactly equivalent to *(x+y), so you could change Line 4 to grid[0] = 34; to make it more readable (this is why grid[2] will do the same thing as 2[grid]!)
An array is simply a contiguous block of memory. Therefore it has a starting address.
int * grid;
Is the C representation of the address of an integer, you can read the * as 'pointer'. Since your array is an array of integers, the address of the first element in the array is effectively the same as the address of the array. Hence line 3
grid = new int[grid_x];
allocates enough memory (on the heap) to hold the array and places its address in the grid variable. At this point the content of that memory is whatever it was when the physical silicon was last used. Reading from uninitialised memory will result in unpredictable values, hence your observation that leaving out line 4 results in strange output.
Remember that * pointer? On line four you can read it as 'the content of the pointer' and therefore
*grid = 34;
means set the content of the memory pointed to by grid to the value 34. But line 3 gave grid the address of the first element of the array. So line 4 sets the first element of the array to be 34.
In C, arrays use a zero-based index, which means that the first element of the array is number 0 and the last is number-of-elements-in-the-array - 1. So one way of filling the array is to index each element in turn to set a value to it.
for(int index = 0; index < grid_x; index++)
{
grid[index] = 34;
}
Alternatively, you could continue to use a pointer to do the same job.
for(int* pointerToElement = grid; 0 < grid_x; grid_x-- )
{
// save 34 to the address held by the pointer
/// and post-increment the pointer to the next element.
*pointerToElement++ = 34;
}
Have fun with arrays and pointers, they consistently provide a huge range of opportunities to spend sleepless hours wondering why your code doesn't work, PC reboots, router catches fire, etc, etc.
int grid_x = 5
int * grid;
grid = new int[grid_x];
*grid = 34;
cout << grid[0];
Should line 3 create an array with 5 elements? Or fill the first
element with the number 5?
Definitely the former. With the operator "new" you are allocating memory
Line 4 fills the first element, how do I fill the rest?
Use operator [], e.g.:
for int (i=0; i < grid_x; i++) { //Reset the buffer
grid[i] = 0;
}
Without line 4, line 5 reads "-842150451".
You are just reading uninitialized memory, it could be any value.
I don't understand what is going on, I'm trying to create a 2
dimensional array using x and y values specified by the user, and then
fill each element one by one with numeric values also specified by the
user. My above code was an attempt to try it out with a 1 dimensional
array first.
Other users explained how to use vectors. If you have to set only once the size of your array, I usually prefer boost::scoped_array which takes care of deleting when the variable goes out of scope.
For a two dimensional array of size not known at compile time, you need something a little bit trickier, like a scoped_array of scoped_arrays. Creating it will require necessarily a for loop, though.
using boost::scoped_array;
int grid_x;
int grid_y;
///Reading values from user...
scoped_array<scoped_array<int> > grid(new scoped_array<int> [grid_x]);
for (int i = 0; i < grid_x; i++)
grid[i] = scoped_array<int>(new int[grid_y] );
You will be able then to access your grid elements as
grid[x][y];
Note:
It would work also taking scoped_array out of the game,
typedef int* p_int_t;
p_int_t* grid = new p_int_t [grid_x];
for (int i = 0; i < grid_x; i++)
grid[i] = new int[grid_y];
but then you would have to take care of deletion at the end of the array's life, of ALL sub arrays.

Not getting the input values when printing vector of pairs

I want to add a pair to a vector of pairs.
When I print the vector elements, I don't get the integers I input.
Please help.
#include<iostream>
#include<vector>
#include<utility>
using namespace std;
int main()
{
vector<vector<unsigned long int> >matrix;
vector<pair<int,int> >pmat;
int L;
cin>>L;
int n1, n2;
pmat.resize(L);
for(int k = 0; k<L; k++)
{
cin>>n1>>n2;
pair<int,int> p = make_pair(n1,n2);
cout<<p.first<<p.second<<endl;
pmat.push_back(p);
}
for(int k = 0; k<L; k++)
{
cout<<pmat[k].first<<','<<pmat[k].second<<' ';
}
cout<<endl;
return 0;
}
Method 1:
Delete this line:
pmat.resize(L);
You don't need to resize it in the first place as you do push_back() when adding afterwards.
Method 2:
Change the following line
pmat.push_back(p);
to
pmat[k] = p;
You can do resize() in the first place, but after this, you should not use push_back() when adding, just use pmat[k] = p.
PS: you should not mix these two ways up. Always use one of them consistently.
Since you're using pmat.resize(L) and L times pmat.push_back(...), you're ending up having stored 2 * L entries in your vector. However you're printing just the first half, index 0 to L - 1. The values you want are stored from index L to 2 * L - 1.
Just change pmat.resize(L) to pmat.reserve(L).
Alternatively, you can use the resize(L), but to end up with L entries, you need to store each input pair to pmat[k], hence you write pmat[k] = p;.
As a rule of thumb, I recommend using the reserve + push_back approach if you know how many elements you're going to add. The reason is, that resize initializes the elements, while reserving just asserts that there will be enough space and no reallocation will be necessary with any following push_back.
You don't want to add more pairs after you allocated them. You can now directly access them.
Just use pmat[k] = p; instead of pmat.push_back(p);
If you print the size of the vector after reading the values, you will notice a small problem with your program:
./test
2
1 2
12
3 4
34
Size of the vector: 4
0,0 0,0
Huh? Even though I only entered 2 pairs, the size of the vector is 4. How did this happen?
If you look at the documentation for resize, it says
Resizes the container to contain count elements.
So even before you read any values, your vector will already contain 2 elements! Those will be default-constructed and therefore be 0. When you then push_pack the elements you read in, those will land at the indices 2 and 3 in the vector, so the end vector has twice as much elements as you wanted (4 in this case). You only print out the first half, which are the zero values.
The solution is to use reserve instead of resize, which doesn't create the elements but only reserves space for them, or just delete the call to resize. Using reserve is more efficient though, because then the vector will only need to allocate memory once.
pmat.resize(L);
if vector in empty its going to initialize a vector pmat with size L then assign default values to vector so now pmat size is L with default values
for(int k = 0; k<L; k++)
{
cin>>n1>>n2;
pair<int,int> p = make_pair(n1,n2);
cout<<p.first<<p.second<<endl;
pmat.push_back(p);
}
then u r pushing values to pmat L times so the final size is 2*L
for(int k = 0; k<L; k++)
{
cout<<pmat[k].first<<','<<pmat[k].second<<' ';
}
here u r going to read from 0 to L-1 , it contains default values you can see your values from L-1 to 2L-1.
so finally what i want say is use reserve instead of resize
or
pmat.resize(L); comment this line