1

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.

Liam Goodacre
  • 381
  • 1
  • 10
  • Can you describe the actual thing you are trying to solve? That might help us give you a better/different/more concrete solution. – NathanOliver Feb 22 '21 at 18:51
  • 1
    can you please clarify if the subsequence is contiguous? If it is the question boils down to finding `begin` and `end` of the subsequence – 463035818_is_not_an_ai Feb 22 '21 at 18:52
  • What are `part` and `part2`? Are they indices into the original vector? It's not clear what you're trying to do. Please describe the problem more precisely. – cigien Feb 22 '21 at 18:56
  • do you also need to handle eg `part = {1,3,5}; part2 = {2,4}` ? – 463035818_is_not_an_ai Feb 22 '21 at 18:57
  • as you already have `part` and `part2` you could store indices instead of the element and rotate `part` and `part2` instead of `whole`. This could be an intersting question but there is too little details to give a concise answer – 463035818_is_not_an_ai Feb 22 '21 at 18:59
  • So have you attempted or tried [std::rotate](https://en.cppreference.com/w/cpp/algorithm/rotate)? If not, there is no harm in experimenting to see what works and what doesn't. If it doesn't work or you have trouble with it, then maybe state what issues you're having with it. – PaulMcKenzie Feb 22 '21 at 19:02
  • 1
    I have edited the original post; please see if it makes more sense now. In the real use-case, I will be modifying a vector of pointers, but ints seem to be clearer for the example. – Liam Goodacre Feb 23 '21 at 05:23
  • Thanks for the edit, it's much clearer now. I've retracted my close vote as well. – cigien Feb 23 '21 at 05:37

0 Answers0