C++. Weighted std::shuffle

后端 未结 1 1512
挽巷
挽巷 2021-01-18 06:19

Is there a way to do nice and elegant weighted shuffling using standard library? There is std::discrete_distribution. What I want is something like this:

相关标签:
1条回答
  • 2021-01-18 06:29

    If OP intent is to shuffle a list r of items

    such that, given a list of weights w, the element a[i] with weight w[i] should be the first element of the random shuffle r with probability w[i]/sum(w).

    As stated in the page linked by Severin Pappadeux:

    Weighted random shuffling is the same as weighted random sampling from a list a without replacement. That is, choose with probability w[i]/sum(w) element a[i] from a. Store this element in a list r. Then, remove element a[i] from a and w[i] from w, and select a new element of the modified list a, and so on until a is empty.

    I'am not aware of such an algorithm in the Standard Library, but a simple implementation could be:

    #include <random>
    #include <algorithm>
    #include <iterator>
    
    template <class D, class W, class URBG>
    void weighted_shuffle
        ( D first, D last
        , W first_weight, W last_weight
        , URBG&& g )
    {
        while (first != last and first_weight != last_weight)
        {
            std::discrete_distribution dd(first_weight, last_weight);
            auto i = dd(g);
            if ( i )
            {
                std::iter_swap(first, std::next(first, i));
                std::iter_swap(first_weight, std::next(first_weight, i));
            }
            ++first;
            ++first_weight;
        }
    }
    

    Live example HERE.

    0 讨论(0)
提交回复
热议问题