33 auto const end = range.end();
34 auto itr = range.begin();
38 throw std::invalid_argument{
"Range [start, end) is empty."};
41 std::random_device rd;
42 std::mt19937 gen(rd());
44 using RangeValue = std::ranges::range_value_t<
decltype(range)>;
45 auto consume_itr = [&itr]() ->
decltype(
auto)
47 using reference_type = std::ranges::range_reference_t<
decltype(range)>;
48 if constexpr (std::is_reference_v<reference_type>)
50 return std::move(*itr);
58 RangeValue result = consume_itr();
62 std::size_t count = 1;
64 for (; itr != end; ++itr, ++count)
66 std::uniform_int_distribution<size_t> distrib(0, count);
67 if (distrib(gen) == 0)
69 result = consume_itr();
103 throw std::invalid_argument{
"Data is empty."};
106 const auto sumOfWeights =
107 std::accumulate(data.begin(), data.end(), 0u,
108 [](
unsigned sum,
const WeightedElement<T>& element) { return sum + element.weight; });
110 if (sumOfWeights == 0u)
112 throw std::invalid_argument{
"Sum of weights cannot be zero."};
117 auto currentSum = 0u;
119 for (
const auto& elem : data)
121 currentSum += elem.weight;
123 if (currentSum > targetWeightValue)
129 return data.back().value;