How to rotate a dynamic array to the right? - c++

I have a custom array object. It has two main variables:
m_array = Pointer to dynamic array.
m_size - The size of the array. The size for this array is 10.
When I rotate to the left, this works fine:
std::rotate(m_array + 0, m_array + 1, m_array + m_size);
This is equivalent to:
// simple rotation to the left
std::rotate(v.begin(), v.begin() + 1, v.end());
When I try rotating to the right, I'm getting a runtime error.
I need the equivalent of this:
// simple rotation to the right
std::rotate(v.rbegin(), v.rbegin() + 1, v.rend());
I tried this:
std::rotate(m_array + m_size, m_array + m_size + 1, m_array + 0);
I get the error: Invalid iterator range
So, I thought this was m_size, so I tried this:
std::rotate(m_array + m_size - 1, m_array + (m_size - 1) + 1, m_array + 0);
And I get the same error.
Thoughts are welcomed.
The source I tried to follow:
http://en.cppreference.com/w/cpp/algorithm/rotate

To do a right rotation (to borrow your phrase), you want the range to be everything but the last element in the array. I'll leave it to you to adapt this code to work on variable-sized arrays.
#include <algorithm>
#include <iostream>
int main() {
int data[10] = { 0, 1, 2, 3, 4,
5, 6, 7, 8, 9 };
auto print_all = [&data]() {
for(auto v: data) {
std::cout << v << ' ';
}
std::cout << '\n';
};
print_all();
// rotate elements to the left
std::rotate(data, data + 1, data + 10);
print_all();
// rotate element to the right, back to the original position
std::rotate(data, data + 9, data + 10);
print_all();
return 0;
}
My output looks like this:
./rotate
0 1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 0
0 1 2 3 4 5 6 7 8 9

The reason std::rotate(v.rbegin(), v.rbegin() + 1, v.rend()) works is that it uses reverse iterators. That means that v.rbegin() + 1 is actually decrementing the position in the array and is equal to v.begin() + v.size() - 1.
When using raw pointer arithmetic, there is no way to get the same reverse iterating behavior. You will have to manually translate the left rotation to a right rotation. This can easily be done by flipping the rotate position about the center of the array and performing a left rotate.
Left or right rotation can be boiled down to dividing an array into 2 sections and then swapping them. Whether it is a left rotation or right rotation just dictates where the division is made. For a left rotate by k, the rotation point is at k mod N. For a right rotate, the rotation point is at -k mod N where N is the total length of the array. This selects the index in the original array you would like to be at index 0 of the newly rotated array.
So the following right rotate by 1,
std::rotate(v.rbegin(), v.rbegin() + 1, v.rend())
is equivalent to using raw pointers in the following way:
int* p = &v[0];
int n = v.size();
int k = -1;
std::rotate(p, p + mod(k, n), p + n);
where mod() is the modulo operation (basically the % operator that always wraps to a positive number):
int mod(int x, int y) { return ((x % y) + y) % y; }

Related

Longest Increasing and Decreasing subsequence (Top-Down with memoization)

Question - Given an array of integers, A of length N, find the length of longest subsequence which is first increasing then decreasing.
Input:[1, 11, 2, 10, 4, 5, 2, 1]
Output: 6
Explanation:[1 2 10 4 2 1] is the longest subsequence.
I wrote a top-down approach. I have five arguments - vector A(containing the sequence), start index(denoting the current index), previous value, large(denoting maximum value in current subsequence) and map(m) STL.
For the backtrack approach I have two cases -
element is excluded - In this case we move to next element(start+1). prev and large remains same.
element is included - having two cases
a. if current value(A[start]) is greater than prev and prev == large then this is the case
of increasing sequence. Then equation becomes 1 + LS(start+1, A[start], A[start]) i.e.
prev becomes current element(A[start]) and largest element also becomes A[start].
b. if current value (A[start]) is lesser than prev and current (A[start]) < large then
this is the case of decreasing sequence. Then equation becomes 1 + LS(start+1, A[start],
large) i.e. prev becomes current element(A[start]) and largest element remains same i.e.
large.
Base Cases -
if current index is out of the array i.e. start == end then return 0.
if sequence is decreasing and then increasing then return 0.
i.e. if(current> previous and previous < maximum value) then return 0.
This is not an optimized approach approach as map.find() is itself a costly operation. Can someone suggest optimized top-down approach with memoization.
int LS(const vector<int> &A, int start, int end, int prev, int large, map<string, int>&m){
if(start == end){return 0;}
if(A[start] > prev && prev < large){
return 0;
}
string key = to_string(start) + '|' + to_string(prev) + '|' + to_string(large);
if(m.find(key) == m.end()){
int excl = LS(A, start+1, end, prev, large, m);
int incl = 0;
if(((A[start] > prev)&&(prev==large))){
incl = 1 + LS(A, start+1, end, A[start],A[start], m);
}else if(((A[start]<prev)&&(A[start]<large))){
incl = 1+ LS(A, start+1, end, A[start], large, m);
}
m[key] = max(incl, excl);
}
return m[key];
}
int Solution::longestSubsequenceLength(const vector<int> &A) {
map<string, int>m;
return LS(A, 0, A.size(), INT_MIN, INT_MIN, m);
}
Not sure about top-down but it seems we could use the classic LIS algorithm to just approach each element from "both sides" as it were. Here's the example with each element as the rightmost and leftmost, respectively, as we iterate from both directions. We can see three instances of a valid sequence of length 6:
[1, 11, 2, 10, 4, 5, 2, 1]
1 11 11 10 4 2 1
1 2 2 1
1 2 10 10 4 2 1
1 2 4 4 2 1
1 2 4 5 5 2 1
1 2 2 1

MaxDoubleSliceSum - codility

I'm trying to solve MexDoubleSliceSum problem without Kandane's bidirectional algorithm.
Problem Definition:
A non-empty array A consisting of N integers is given.
A triplet (X, Y, Z), such that 0 ≤ X < Y < Z < N, is called a double
slice.
The sum of double slice (X, Y, Z) is the total of A[X + 1] + A[X + 2]
+ ... + A[Y − 1] + A[Y + 1] + A[Y + 2] + ... + A[Z − 1].
For example, array A such that:
A[0] = 3
A[1] = 2
A[2] = 6
A[3] = -1
A[4] = 4
A[5] = 5
A[6] = -1
A[7] = 2
The goal is to find the maximal sum of any double slice.
that, given a non-empty array A consisting of N integers, returns the
maximal sum of any double slice.
For example, given:
A[0] = 3
A[1] = 2
A[2] = 6
A[3] = -1
A[4] = 4
A[5] = 5
A[6] = -1
A[7] = 2
the function should return 17, because no double slice of array A has
a sum of greater than 17.
I have figured out following idea:
I'm taking a slice and putting lever (value in the middle that's being dropped) to lowest value included in this slice. If I notice that next value is lowering total sum i'm changing lever to it and reducing sum with values before last lever(including old lever).
int solution(vector<int> &A) {
if(A.size()<4)
return 0;
int lever=A[1];
int sum=-lever;
int presliceValue=0;
int maxVal=A[1];
for(int i=1;i<A.size()-1;i++){
if(sum+A[i]<sum || A[i]<lever){
sum+=lever;
if(presliceValue<0)
sum=sum-presliceValue;
lever=A[i];
presliceValue=sum+lever;
}
else
sum=sum+A[i];
if(sum>maxVal)
maxVal=sum;
}
return maxVal;
}
This solution returns wrong value on few test cases (unfortunately cannot tell what's tested values):
unfortunately i cannot reproduce following error and codility does not share test values.
Failed Test cases
many the same small sequences, length = ~100,000
large random: random, length = ~100,000
random, numbers from -30 to 30, length = 300
random, numbers form -104 to 104, length = 70

Eigen matrix rowwise addition

I have an Nx3 Eigen matrix representing a bunch of locations of vertices in 3d space.
I'm trying to add a 1x3 matrix to each row in the Nx3 to move every point a given direction and distance.
#include <Eigen/Dense>
int N = 20; //for example
MatrixXf N3(N, 3);
N3.fill(2);
MatrixXf origin(1, 3);
origin << 1, 2, 3;
Now I want to add origin to each row in N3 so N3 becomes 3, 4, 5 in each row. (The values in N3 are all different 3d vertex locations in the real code.)
3, 4, 5
3, 4, 5
3, 4, 5 etc...
you may just write
N3 += origin.replicate(N,1);
note that no temporary matrix is created, replicate() returns an expression.
Try this (untested)
for (int i = 0 ; i < 3 ; i++)
N3.block(i, 0, 1, 3) = N3.block(i, 0, 1, 3) + origin
I do not remember if += is supported
MatrixXf result = N3 + MatrixXf::Constant(1, N, 1) * origin;
Should be simple as that.

Mathematically rotate an array of ordered numbers

Suppose you have a set of numbers in a given domain, for example: [-4,4]
Also suppose that this set of numbers is in an array, and in numerical order, like so:
[-4, -3 -2, -1, 0, 1, 2, 3, 4]
Now suppose I would like to create a new zero-point for this set of numbers, like so: (I select -2 to be my new axis, and all elements are shifted accordingly)
Original: [-4, -3 -2, -1, 0, 1, 2, 3, 4]
Zeroed: [-2, -1 0, 1, 2, 3, 4, -4, -3]
With the new zeroed array, lets say I have a function called:
"int getElementRelativeToZeroPosition(int zeroPos, int valueFromOriginalArray, int startDomain, int endDomain) {...}"
with example usage:
I am given 3 of the original array, and would like to see where it mapped to on the zeroed array, with the zero on -2.
getElementRelativeToZeroPosition(-2, 3, -4, 4) = -4
Without having to create any arrays and move elements around for this mapping, how would I mathematically produce the desired result of the function above?
I would proceed this way:
Get index of original zero position
Get index of new zero position (ie. index of -2 in you example)
Get index of searched position (index of 3)
Compute move vector between new and original zero position
Apply move vector to searched position modulo the array size to perform the rotation
Provided your array is zero-based:
index(0) => 4
index(-2) => 2
index(3) => 7
array_size => 9
move_vector => index(0) - index(-2)
=> 4 - 2 => +2
new_pos(3) => (index(3) + move_vector) modulo array_size
=> (7 + 2) mod 9 => 0
value_at(0) => -4
That's it
Mathematically speaking, if you have an implicit set of integers given by an inclusive range [start, stop], the choice of choosing a new zero point is really a choosing of an index to start at. After you compute this index, you can compute the index of your query point (in the original domain), and find the difference between them to get the offset:
For example:
Given: range [-4, 4], assume zero-indexed array (0,...,8) corresponding to values in the range
length(range) = 4 - (-4) + 1= 9
Choose new 'zero point' of -2.
Index of -2 is -2 - (-4) = -2 + 4 = 2
Query for position of 3:
Index in original range: 3 - (-4) = 3 + 4 = 7
Find offset of 3 in zeroed array:
This is the difference between the indices in the original array
7 - 2 = 5, so the element 3 is five hops away from element -2. Equivalently, it's 5-len(range) = 5 - 9 = -4 hops away. You can take the min(abs(5), abs(-4)) to see which one you'd prefer to take.
you can write a doubled linked list, with a head-node which points to the beginning
struct nodeItem
{
nodeItem* pev = nullptr;
nodeItem* next = nullptr;
int value = 0;
}
class Node
{
private:
nodeItem* head;
public:
void SetHeadToValue(int value);
...
}
The last value should point with next to the first one, so you have a circular list.
To figur out, if you are at the end of the list, you have to check if the item is equal to the head node

Navigating an Array with Column Boundaries

Let's say there is a square 2 dimensional array of N x N, represented as a one dimension array. Let the array be 5x5, like below, and the values in the array are not significant.
std::vector< int > array {
0, 1, 2, 3, 4,
5, 6, 7, 8, 9,
0, 1, 2, 3, 4,
5, 6, 7, 8, 9,
0, 1, 2, 3, 4
};
If we say that there are 5 rows and 5 columns in this array, how can one detect if they are on the edge of a row? For instance, if you are on the index of where 9 is on the 4th row, how can you know that you can go left without changing rows, but going right will advance to the next row? How can one access a cell's neighbors with respect to edges? The index of where 9 is on the 4th row does not have a right neighbor.
The only way I can think of how to do this would be the current index, in which case is
int index = row * num_cols + col
and perhaps use modulus (index % 5 == 0) to determine if on edge. But that does not determine if we can go left or right.
Your formula
int index = row * num_cols + col;
Going up or down is equivalent to adding / subtracting num_cols.
is correct. The reverse of it is
int row = index / num_cols;
int col = index % num_cols;
You know you're on the left edge when (index % num_cols) == 0.
You know you're on the right edge when (index % num_cols) == num_cols-1.
You can use
int row = index / N;
int col = index % N;
to get the row and column indices. For example, the 9th entry has row index 9/5=1 and column index 9%5=4.
Having computed the (row, col) coordinate, you can determine if it has the left or right neighbors. When col == 0, you don't have a left neighbor; when col == N-1, you don't have a right neighbor.