1#ifndef UTILS_COLLECTIONS_H
2#define UTILS_COLLECTIONS_H
13#include <unordered_map>
14#include <unordered_set>
20extern void sort_unique(std::vector<T>& vec)
22 std::sort(vec.begin(), vec.end());
23 vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
27extern bool is_sorted_unique(
const std::vector<T>& values)
29 for (
size_t i = 1; i < values.size(); ++i) {
30 if (values[i - 1] >= values[i])
return false;
36extern bool all_values_unique(
const std::vector<T>& v)
38 std::unordered_set<T> s(v.begin(), v.end());
39 return s.size() == v.size();
43bool in_bounds(std::signed_integral
auto index,
const T& container)
45 return index >= 0 &&
static_cast<size_t>(index) < container.size();
49bool in_bounds(std::unsigned_integral
auto index,
const T& container)
51 return static_cast<size_t>(index) < container.size();
55T swap_and_pop_from_vector(std::vector<T>& vec,
size_t pos)
57 assert(in_bounds(pos, vec));
59 std::swap(vec[pos], vec.back());
65void release_vector_memory(std::vector<T>& vec)
67 std::vector<T>().swap(vec);
70template <
class KeyType,
class ValueType>
71ValueType get_value_or_default(
72 const std::unordered_map<KeyType, ValueType>& dict,
74 const ValueType& default_value)
76 auto it = dict.find(key);
77 if (it != dict.end()) {
83template <
typename ElemTo,
typename Collection,
typename MapFunc>
84std::vector<ElemTo> map_vector(
const Collection& collection, MapFunc map_func)
86 std::vector<ElemTo> transformed;
87 transformed.reserve(collection.size());
89 std::begin(collection),
91 std::back_inserter(transformed),
96template <
typename T,
typename Collection>
97std::vector<T> sorted(Collection&& collection)
99 std::vector<T> vec(std::forward<Collection>(collection));
100 std::sort(vec.begin(), vec.end());
105int estimate_vector_bytes(
int num_elements)
114 size += 2 *
sizeof(
void*);
115 size +=
sizeof(std::vector<T>);
116 size += num_elements *
sizeof(T);
121int _estimate_hash_table_bytes(
int num_entries)
130 assert(num_entries < (1 << 28));
139 const auto bounds = {
140 2, 5, 11, 23, 47, 97, 199,
141 409, 823, 1741, 3469, 6949, 14033, 28411,
142 57557, 116731, 236897, 480881, 976369, 1982627, 4026031,
143 8175383, 16601593, 33712729, 68460391, 139022417, 282312799};
145 for (
int bound : bounds) {
146 if (num_entries < bound) {
153 size += 2 *
sizeof(
void*);
155 using Entry =
typename T::value_type;
156 size += num_entries *
sizeof(Entry);
157 size += num_entries *
sizeof(Entry*);
158 size += num_entries *
sizeof(
void*);
159 size += num_buckets *
sizeof(
void*);
164int estimate_unordered_set_bytes(
int num_entries)
167 return _estimate_hash_table_bytes<std::unordered_set<T>>(num_entries);
170template <
typename Key,
typename Value>
171int estimate_unordered_map_bytes(
int num_entries)
174 return _estimate_hash_table_bytes<std::unordered_map<Key, Value>>(
178template <
class I1,
class I2>
179bool have_common_element(I1 first1, I1 last1, I2 first2, I2 last2)
181 while (first1 != last1 && first2 != last2) {
182 if (*first1 < *first2) {
184 }
else if (*first2 < *first1) {
194template <
class Range1,
class Range2>
195bool have_common_element(
const Range1& range1,
const Range2& range2)
197 return have_common_element(
205template <
typename T,
typename A>
207merge_sorted(
const std::vector<T, A>& left,
const std::vector<T, A>& right)
209 std::vector<T, A> merged;
210 merged.reserve(left.size() + right.size());
211 std::ranges::merge(left, right, std::back_inserter(merged));
215template <
typename T,
typename A>
216void insert_set(std::vector<T, A>& lhs, T element)
218 assert(std::is_sorted(lhs.begin(), lhs.end()));
220 auto it = std::lower_bound(lhs.begin(), lhs.end(), element);
221 if (it == lhs.end() || *it != element) {
222 lhs.insert(it, std::move(element));
226template <
typename T,
typename A>
227void insert_set(std::vector<T, A>& lhs,
const std::vector<T, A>& rhs)
229 for (
const auto& element : rhs) {
230 insert_set(lhs, element);
234template <std::ranges::input_range T>
235bool contains(T&& range,
const std::ranges::range_value_t<T>& val)
237 return std::ranges::find(range, val) != std::ranges::end(range);
241extern bool is_unique(
const std::vector<T>& values)
243 std::vector<T> temp(values.begin(), values.end());
244 std::ranges::sort(temp);
245 return is_sorted_unique(temp);
248template <
typename Iterator,
typename Sentinel,
typename T>
249auto find_sorted(Iterator begin, Sentinel end,
const T& elem)
251 auto it = std::lower_bound(begin, end, elem);
252 return it != end && *it == elem ? it : end;
256void release_container_memory(T& container)