I want to rotate a subset of an vector inside the whole vector. The subset to be rotated is defined by another vector.
What I want to achieve is this:
template<typename CONTAINER>
void rotateSubset(CONTAINER& whole, const CONTAINER& subset)
{
// ???
}
auto whole = std::vector<int> {1, 2, 3, 4, 5};
auto part = std::vector<int> { 2, 3, 4 };
auto part2 = std::vector<int> {1, 5};
rotateSubset(whole, part);
// whole is now 1, 3, 4, 2, 5;
rotateSubset(whole, part2);
// whole is now 5, 3, 4, 2, 1
The given subset is guaranteed to be contained by the larger whole set. The subset could be any subset of the whole, in any order; it need not be contiguous.
This is what I've tried so far:
template<typename CONTAINER>
void rotateSubset(CONTAINER& whole, const CONTAINER& subset)
{
assert(subset.isSubsetOf(whole)); // don't worry about the implementation of this pseudo-code for now
std::rotate(subset.begin(), subset.end());
if (subset.size() == whole.size())
whole = subset;
else
{
// copy the subset vector into the whole vector in the new order
auto it = subset.cbegin();
for (auto& element : whole)
if (std::find(subset.cbegin(), subset.cend(), element) != subset.cend())
element = *it++;
}
}
This works, however it feels a bit sketchy to me. I was wondering if there was some neat way of using the Ranges
library in C++20 to do it. Something like this:
// PSEUDO-CODE
auto subRange = std::ranges::views::subset(whole, part);
std::rotate(subRange.begin(), subRange.end());
I don't have a good knowledge of the Ranges library yet, but I think that something like this should be possible.
Please note: I want the solution to use a simple std::rotate()
at some level. The reason for this is that I want to perform other similar functions on a sub-set as well (i.e. std::shuffle()
), so the actual function that does the rotation / shuffling / whatever will be a variable in the final version. It's the "altering a subset" part that I'm really interested in here; the rest will come together later.