34 auto const end = range.end();
35 auto itr = range.begin();
39 throw std::invalid_argument{
"Range [start, end) is empty."};
42 std::random_device rd;
43 std::mt19937 gen(rd());
45 using RangeValue = std::ranges::range_value_t<
decltype(range)>;
46 auto consume_itr = [&itr]() ->
decltype(
auto)
48 using reference_type = std::ranges::range_reference_t<
decltype(range)>;
49 if constexpr (std::is_reference_v<reference_type>)
51 return std::move(*itr);
59 RangeValue result = consume_itr();
63 std::size_t count = 1;
65 for (; itr != end; ++itr, ++count)
67 std::uniform_int_distribution<size_t> distrib(0, count);
68 if (distrib(gen) == 0)
70 result = consume_itr();
104 throw std::invalid_argument{
"Data is empty."};
107 const auto sumOfWeights =
108 std::accumulate(data.begin(), data.end(), 0u,
109 [](
unsigned sum,
const WeightedElement<T>& element) { return sum + element.weight; });
111 if (sumOfWeights == 0u)
113 throw std::invalid_argument{
"Sum of weights cannot be zero."};
118 auto currentSum = 0u;
120 for (
const auto& elem : data)
122 currentSum += elem.weight;
124 if (currentSum > targetWeightValue)
130 return data.back().value;