C++ move a range by a non-negative displacement? - c++

I was faced with a need to move a range of elements backward by a certain (possibly zero) displacement. To illustrate, here is some code:
std::vector<int> arr[4] = {{1}, {2}, {3}, {4}};
std::move(arr + 2, arr + 4, arr + 2 - k); // k can be either 0, 1, or 2,
// depending on how far much I want to move the elements
This works as expected when k is nonzero, but fails when k is zero (I expect the move to become a no-op when k=0).
The following code, when compiled in GCC will cause arr[2] and arr[3] to lose all their elements:
int main() {
std::vector<int> arr[4] = {{1}, {2}, {3}, {4}};
std::move(arr + 2, arr + 4, arr + 2);
for(int i = 0; i < 4; ++i) std::cout << arr[i].size() << ' '; // prints "1 1 0 0 "
std::cout << std::endl;
}
C++ reference says that std::move's destination should not be in the range [first, last), and my code has been in violation of this.
After some digging, I found that self move assignment (i.e. x = std::move(x)) is not expected to be a no-op, so that seems to be why I'm not allowed to do a no-op range std::move.
This issue would also happen if I want to move a range of elements forward by a certain (possibly zero) displacement.
To solve this problem, I could check explicitly that k is nonzero before moving. But is this the idiomatic C++ way?

Yes, such a check would be very typical. Even if x[i]=x[i+0]; were a no-op you would still want to skip the loop processing if possible and that's what the zero-displacement check would provide.

Related

How to compare all elements of vector one to vector two and if a max element exists then comparing all the elements of vector two to vector three?

I want to compare all element of vector x to all elements of vector y and if I find a element greater in vector y than being compared to, I have to take that particular element of vector y and compare to all elements of vector z and if it is true return true else if i don't find a greater element in first iteration i,e when elements of vector x are compared to vector y i have to break the loop and return false.
I tried to iterate through all the elements of stackarmies but I don't know how to take the first element of vector one and compare with all the elements of vector, since all the vectors are merged into the last vector.
vector<int> stack;
int noofstack, noofoperations, stackno, OperationType;
// Taking the input number of stacks
cin >> noofstack;
vector<vector<int>> stackarmies;
for (int i = 0; i < noofstack; i++)
{
int stacksize;
//Since vectors are dynamic and we don't need to declare the size but as per the problem statement I've added it/
cin >> stacksize;
for (int k = 0; k < stacksize; k++)
{
//Taking the input of all the vectors one by one and then adding all the vectors into one vector
int armyheight;
cin>>armyheight;
stack.push_back(armyheight);
}
stackarmies.push_back(stack);
Test cases
Input 1
2
3 3 5 4
3 1 1 2
Resulting stackarmies: { {3, 5, 4}, {3, 5, 4, 1, 1, 2} }
Desired output: False
We will take first element of vector 1 : 3 and compare with all
elements of vector 2 , in vector 2 no element is greater than 3.
Input 2
2
3 1 0 4
3 2 1 3
Resulting stackarmies: { {1, 0, 4}, {1, 0, 4, 2, 1, 3} }
Desired output: True
We will take first element of vector 1 : 1 and compare with all
elements of vector 2, in vector 2, the first element is greater than 1,
so true
Input 3
2
3 1 9 0
2 0 11
Resulting stackarmies: { {1, 9, 0}, {1, 9, 0, 0, 11} }
Desired output: True
We will take first element of vector 1 : 1 and compare with all
elements of vector 2, in vector 2, the last element is greater than 1,
so true
Input 4
3
3 0 8 0
3 4 0 11
3 0 9 0
Resulting stackarmies: { {0, 8, 0}, {0, 8, 0, 4, 0, 11} , {0, 8, 0, 4, 0, 11, 0, 9, 0} }
Desired output: True
We will take the second element of vector 1: 8 and compare with
all elements of vector 2 , 11 is greater than 8 so we will compare 11 of
vector 2 with vector , since there are no values greater than 11, so it's
false
I don't know how to take the first element of vector one and compare with all the elements of vector, since all the vectors are merged into the last vector.
You're getting ahead of yourself. Why do you want all the vectors merged into the last vector? Answer: you don't; that's just what happened. Why did all the vectors merge into the last vector? Answer: because you have a bug in your code that reads the data. Fix that bug instead of spending ten times as much effort trying to handle the malformed data.
That whole spiel about what you intend to do next is nothing more than a distraction that wastes the time of the people from whom you are asking help. Ask for help with the real problem (the loading bug) instead of driving people away with a confusing question that assumes bad data is good.
There are several ways to fix the bug. I think the most helpful approach is one that would have avoided the bug in the first place. You try to do too much in a single function. Divide and conquer; when you have a non-trivial sub-step, create a function to handle it. Good programming practices lead to fewer bugs.
Specifically, reading the heights of the fighters in a stack is non-trivial. Delegate that to a helper and reduce the body of your outer for loop to a single line.
for (int i = 0; i < noofstack; i++)
{
//* This is non-trivial, so use a helper function.
stackarmies.push_back(read_fighter_heights());
}
This helper function is responsible for reading a line of data, generating a stack (a vector<int>) from it, and returning that stack. That covers most of the body of your loop, leaving only the simple task of pushing the returned stack onto your vector of stacks.
Creating this helper function from your existing code is fairly simple. Mostly, just move the body of the loop into an appropriate function definition. In addition, you should notice that stack is needed (only) in this function, so also move that variable's declaration into the new function's definition.
vector<int> read_fighter_heights()
{
vector<int> stack;
int stacksize;
//Since vectors are dynamic and we don't need to declare the size but as per the problem statement I've added it/
cin >> stacksize;
for (int k = 0; k < stacksize; k++)
{
//Taking the input of all the vectors one by one and then adding all the vectors into one vector
int armyheight;
cin>>armyheight; //* Reading a single integer is trivial, so no need for another function here.
stack.push_back(armyheight);
}
return stack;
}
Presto! Problem solved. All you had to do was be more organized.
Addendum: The reason this solves the problem is that extra step of moving the declaration of stack. In the original code, this variable was declared outside the outer loop, and it was never cleared. The result was that it accumulated values from each line that was read. In this version, the variable is re-initialized before reading each line, so values do not accumulate. You could get the same result by moving the line in the original code, without splitting off a new function. However, splitting off a new function is a good habit to get into, as it almost forces you to declare stack at the right level, avoiding the problem in the first place.
bool CompareVectors(vector<vector<int>> st)
{
bool result = true;
for (int k = 0; k < st.size(); k++)
{
if (k != st.size() - 1)
{
if (result)
{
for (auto i = st[k].begin(); i != st[k].end(); ++i)
{
for (auto j = st[k+1].begin(); j != st[k+1].end(); ++j)
{
if (*i < *j)
{
result = true;
break;
}
else
{
result = false;
}
}
if (result)
{
break;
}
}
}
}
}
return result;
}

How can I check equivalency between two arrays in C++?

So I have two arrays and I need to find a way to find the equivalency between two different arrays in C++. This is the function I made:
bool equivalent(int a[], int b[], int n)
for (int i=0; i < n; i++){
if (b[(i + 2) % 5] == a[i])
return true;
else return false;
}
}
and this is the array:
int main() {
cout << boolalpha;
int a1[5] = {1, 2, 3, 4, 5};
int a2[5] = {3, 4, 5, 1, 2};
cout << equivalent(a1, a2, 5) << endl;
I know my arthmetic is correct, because for example, a2[4], 4 plus 2 is 6, mod 5 is 1, and in the a1[0] position, there is a value of 2 which is the same as the a2[4] value. My only problem is, the resultant should be true, but because the for loop starts at 0, the whole function messes up, as the second arrays index would need to start at a different number for it to work. How would I go about solving this?
How would I go about solving this?
By using a debugger. Step through the program line by line. If the behaviour is different than it is supposed to, you've found the problem.
There are two problems with the program:
I know my arthmetic is correct, because for example, a2[4], 4 plus 2 is 6, mod 5 is 1, and in the a1[0] position, there is a value of 2 which is the same as the a2[4] value.
But you're comparing a1[0] with a2[2], not with a2[4]. You've got the order of the arguments reversed.
You only compare a1[0] and then return the result. In order to compare the entire array, you must not return until all elements have been checked (except the branch which returns false can return early).
I think easy way is to convert both array into string then compare both.

Why does using push_back on a vector declared with size result in a vector of zeros?

I made a vector of constant size to store negative values, and then printing the values all I got was zeroes. I just want to know why it is not storing negative values.
#include <iostream>
#include <vector>
int main() {
std::vector<int> v(5);
v.push_back(-1);
v.push_back(-2);
v.push_back(-3);
v.push_back(-4);
v.push_back(-5);
for (int i=0; i<5; i++)
std::cout << v[i] << " "; // All I got was zeroes
}
That's because push_back puts new elements onto the end of the vector.
You can see the effect by running i to 9: the negative numbers will occupy v[5] to v[9].
Writing
std::vector<int> v{-1, -2, -3, -4, -5};
instead is a particularly elegant fix.
The constructor that you invoke fills the first 5 elements with zeros, see here (#3 in the list of overloads):
Constructs the container with count default-inserted instances of T
(where the "default-inserted instance" of an int is 0). What you might have wanted is
std::vector<int> v;
v.reserve(5); /* Prevent unnecessary allocations as you know the desired size. */
v.push_back(-1);
/* ... */
An alternative using the original constructor call is
#include <numeric>
std::vector<int> v(5);
std::iota(v.rbegin(), v.rend(), -v.size());
though this does more work than necessary as every element is first default constructed and then assigned to a new value again.
This is a case where the DRY principle would help you understand your mistake.
vector<int> v(5);
...
for(int i=0;i<5;i++)
Here you are creating an array, for which you think you reserve space for 5 elements. Then you insert those 5 elements. After that you wanted to print contents of the whole array, but instead of just writing v.size(), you repeated the 5, so that your code now reads like "Print first five elements of v", instead of "Print all elements of v".
If you instead wrote what you mean, you'd see that the array actually has 10 elements, not 5.
BTW, since C++11 you can loop over all elements in a more straightforward way:
for(int x : v)
or, if the elements were some more copy-expensive type, you could use references to the elements, even auto-type references:
for(auto& x : v)
This new for-loop syntax is called the range-based for loop.
You can consider the vector a flexible version of the primitive array in C/C++. When you initialize a vector with a size n, the constructed vector has size of n (or maybe larger in the memory, but you don't know since it's implicitly handled by compiler). Note that here n represents the number of entries, but not the actual memory usage (i.e. bytes). If you do not initialize it with a size parameter, the vector is empty with size 0, but in the memory it would have some implicit default memory size.
Let's say your current vector has size 5. And you want to push_back() in another element, then the vector internally will reallocate the entire array into a new memory location which could hold all its old entries plus the new one. So you don't need to reallocate the memory manually by yourself, like what you have to do in C.
Here, in your example, to fill in those 5 negative integers in your vector, there are a couple of ways.
1) You can initialize a vector without specifying the size. And then push in each element you want.
vector<int> v;
for (int i = -1; i >= -5; --i) {
v.push_back(i);
}
2) You can initialize the vector in your way with that size parameter. And then assign them with new values.
vector<int> v(5);
for (int i = 0; i < v.size(); ++i) {
v[i] = -i;
}
3) You can also initialize the vector with those entries when it is constructed.
vector<int> v{-1, -2, -3, -4, -5};
or vector<int> v = {-1, -2, -3, -4, -5};
When you declared the vector with
std::vector<int> v(5);
You made v store five 4-byte spaces in memory (assuming an int = 4 bytes on your system), and by default all of these 4-byte spaces store the bits representing 0's. Then, you pushed 5 more ints (-1, -2, -3, -4, -5) onto the end of the vector with:
v.push_back(-1);
v.push_back(-2);
v.push_back(-3);
v.push_back(-4);
v.push_back(-5);
At this point the vector has 10 elements, the first five being the unknown ints that happen to store 0's on the instance you ran the program. Since your for loop prints the first five elements in the vector, this is why it printed all 0's.
When you declared this line vector<int>v(5) it created a vector of size 5 with default value of all elements 0, at this stage your vector looks like this -
{0, 0, 0, 0, 0}
Now when you called v.push_back(-1) what it did is it pushed -1 to the back of vector increasing its size, now your vector looks like this -
{0, 0, 0, 0, 0, -1}
After every push back is performed your final vector will be - {0, 0, 0, 0, 0, -1, -2, -3, -4, -5}
The size of your vector is now increased to 10 from 5 and when you looped from index 0 to 4 it only printed 0. I hope I explained it well and fix for this is already provided in previous answers.

Add an element at the beginning of an array and shift the rest but keep the size

I need to create a vector/array in the following format:
arr[10] = [1, 2, 3, 4, 5, 6, 7, 8, 9 ,10]
I want to add a new element at the beginning after which all elements are shifted to the right and the last element is deleted. The result should be:
arr[10] = [new_int, 1, 2, 3, 4, 5, 6, 7, 8, 9]
How can I do this in c++? Do I have to write a function or there is already an existing one like .append or .pushback?
If it's an std::vector, the trivial solution is:
vec.pop_back();
vec.insert(vec.begin(), new_int);
The asymptotic complexity is the same as any other method to accomplish this (pop_back() is O(1), insert in head is O(n), no reallocation is ever performed) but it temporarily touches the vector length for no good reason and does overall more bookkeeping.
A better solution (that is fine both for std::vector, std::array as well as for C-style array) is:
std::copy_backward(std::begin(vec), std::end(vec)-1, std::begin(vec)+1);
vec[0] = new_int;
This, again, should have O(n) complexity, but a smaller "offset" (it does exactly what it needs to do, nothing more).
Now, if we move to different data structures the situation is different; with an std::deque you can do as #JesperJuhl shows in his answer; pushing/popping at both ends of a deque costs amortized O(1), so it's reasonably fast for most uses.
Still, if your buffer is fixed in size, generally the natural data structure for the operation you describe is the fixed-size circular buffer; it is not provided by the standard library, but there's an implementation in Boost (besides, it's also a nice exercise to write it yourself, with iterators and everything).
#include <algorithm>
#include <iterator>
...
std::rotate( std::begin(arr), std::end(arr)-1, std::end(arr));
arr[0] = new_int;
The easiest would be to use a std::deque. Then it becomes as simple as
my_deque.pop_back(); // get rid of last element.
my_deque.push_front(42); // put the new element at the front
You can use vector using push and pop. If you want to do it using arrays then you can:
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9 ,10};
int new_value = 20;
for(int i(0); i < 10 - 2; i++){
arr[i + 1] ^= arr[i];
arr[i] ^= arr[i + 1];
arr[i + 1] ^= arr[i];
}
Or you can use a temporary variable instead of XOR operator:
/*
int tmp = arr[i + 1];
arr[i + 1] = arr[i];
arr[i] = tmp;
*/
arr[0] = new_value;
for(int i = 0; i < 10; i++)
std::cout << arr[i] << ", ";
std::vector<int> arr;
arr.insert(arr.begin(), newvalue);
arr.pop_back();

Fixed length structure re-arrange: should I use array or linked list?

This structure will only contain exactly 256 unsigned chars.
The only operation possible is taking random characters from it and putting them in front of the structure.
For example:
A= 'abcdef'
Move character 2 to front
A= 'cabdef'
I first thought of using linked link so that it could work as a queue.
Thing is I heard that arrays are much faster than linked lists for these operations. Is this true?
A linked list will be O(1) and an array will be O(n) for a move operation as you have described. For small n the array will probably be faster, but the only way to know for sure is to benchmark.
In a case like this I would code what's clearest and only worry about efficiency if it proves to be a bottleneck.
P.S. I made an assumption that you already had a pointer to the character you want to move. If this is not the case, then finding the character will be O(n) in the linked list and you will lose any advantages it might have.
Use an array. The linked list will be huge and unwieldy for storage of char data.
A linked list would be a good approach since you don't need to move all the intermediate elements around. std::list works just fine, combined with splice(). You will need an iterator to the element you want to move to the front:
#include <list>
#include <iostream>
#include "prettyprint.hpp"
int main()
{
std::list<int> x { 1, 4, 6, 7, 2 };
auto i = x.begin(); std::advance(i, 2); // i points to 6
std::cout << x << std::endl; // [1, 4, 6, 7, 2]
x.splice(x.begin(), x, i);
std::cout << x << std::endl; // [6, 1, 4, 7, 2]
}
(Using the pretty printer for a quick demo.)
As others have said, whether that's more efficient that a random-access container depends on how you are tracking the element that you want to move.
Update: In light of Steve's remarks I should like to offer a raw C-array solution, too. It has the benefit that you can access it by position in O(1) time and that it requires minimum space:
char y[] = { 'a', 'c', 'Q', '%', '5' };
std::cout << pretty_print_array(y) << std::endl; // [a, c, Q, %, 5]
std::rotate(y, y + 2, y + sizeof(y));
std::cout << pretty_print_array(y) << std::endl; // [Q, %, 5, a, c]
The rotate call could be wrapped in a function:
template <typename T, size_t N>
void bring_forward(T (& a)[N], size_t p) { std::rotate(a, a + p, a + N); }
In C++, you can use a vector instead of array or linked list. The complexity of a Linked List is O(1) like #Mark Ransom said. With the vector, you can use the command rotate to perform the action you desire. The complexity is determined by the number of swaps.
From MSDN, how to use rotate:
const int VECTOR_SIZE = 8;
// Define a template class vector of strings
typedef vector<string> StrVector;
//Define an iterator for template class vector of strings
typedef StrVector::iterator StrVectorIt;
StrVector Tongue_Twister(VECTOR_SIZE);
StrVectorIt start, end, middle, it;
// location of first element of Tongue_Twister
start = Tongue_Twister.begin();
// one past the location last element of Tongue_Twister
end = Tongue_Twister.end();
// Initialize vector Tongue_Twister
Tongue_Twister[0] = "she";
Tongue_Twister[1] = "sells";
Tongue_Twister[2] = "sea";
Tongue_Twister[3] = "shells";
Tongue_Twister[4] = "by";
Tongue_Twister[5] = "the";
Tongue_Twister[6] = "sea";
Tongue_Twister[7] = "shore";
middle = start + 3; // start position for rotating elements
cout << "Before calling rotate" << endl;
// print content of Tongue_Twister
cout << "Try this Tongue Twister:";
for (it = start; it != end; it++)
cout << " " << *it;
// rotate the items in the vector Tongue_Twister by 3 positions
rotate(start, middle, end);
Or you can do it with arrays:
// create an array of 9 elements and rotate the entire array.
int myArray[SIZE] = { 7, 8, 9, 1, 2, 3, 4, 5, 6, };
std::rotate(myArray, myArray + 3, myArray + SIZE);
How fast is this? I don't know. I haven't benchmarked it. But it is much easier than having to manually swap elements of an array.
The array will be O(1) to find the item and O(n) to move it and the other items into the correct position. The linked list will be O(n) to find the item and O(1) to move everything to the right position. The complexity is the same either way.
They're both easy to implement, so implement both of them and run tests to see which one lets your program run faster with real-world data.
C++ arrays are linked lists, so moving an element to the front of your list is cheap, provided you already know where the element is (i.e. you have an iterator on it). Using a vector would cause the entire list to be shifted each time an element is pushed in front of it.