34 auto const end = range.end();
35 auto itr = range.begin();
39 throw std::invalid_argument{
"Range [start, end) is empty."};
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();
97 const auto size1 = std::ranges::distance(range1);
98 const auto size2 = std::ranges::distance(range2);
100 if (size1 + size2 == 0)
102 throw std::invalid_argument{
"Ranges are empty."};
109 return (*std::ranges::next(range1.begin(), index));
112 return (*std::ranges::next(range2.begin(), index - size1));
142 throw std::invalid_argument{
"Data is empty."};
145 const auto sumOfWeights =
146 std::accumulate(data.begin(), data.end(), 0u,
147 [](
unsigned sum,
const WeightedElement<T>& element) { return sum + element.weight; });
149 if (sumOfWeights == 0u)
151 throw std::invalid_argument{
"Sum of weights cannot be zero."};
156 auto currentSum = 0u;
158 for (
const auto& elem : data)
160 currentSum += elem.weight;
162 if (currentSum > targetWeightValue)
168 return data.back().value;