I wrote this function to generate random permutation of input vector, while making sure every element has switched place (for a Secret Santa like purpose).
std::map<std::string, std::string> getPermutation(const std::vector<std::string>& participants)
{
auto permuted = participants;
std::random_device rd;
std::mt19937 g(rd());
bool correctlyPermuted = false;
while(!correctlyPermuted)
{
std::shuffle(permuted.begin(), permuted.end(), g);
auto res = std::mismatch(participants.begin(), participants.end(), permuted.begin(), std::not_equal_to{});
if(res.first == participants.end())
{
correctlyPermuted = true;
}
}
std::map<std::string, std::string> result;
for(int i = 0; i < participants.size(); ++i)
{
result[participants[i]] = permuted[i];
}
return result;
}
You can run code here. Note that's still work in progress, I'm mostly concerned about the function above.
participants
is guaranteed to contain no duplicate elements.
I'm not really concerned with speed - it's supposed to be executed by humans, they are unlikely to notice any performance improvement. Of course, you are welcome to point any obvious performance issues.
However, I'm concerned with the readability of the function, particularly with the use of std::mismatch
to find actually matching elements. It feels too clever, but maybe it's just good use of functional programming and I'm overthinking? It also seems too long for a good function (22 lines), but I can't think of how it could be splitted/shortened logically.